SlideShare a Scribd company logo
1 of 21
Download to read offline
Separating Identity from State
(The Clojure Way)
아꿈사
Cecil
목 차
• 원자(Atom)
• Agent(에이전트)
• STM(Software Transaction Memory)
• 원자와 STM의 비교
순수 함수형 언어는 가변 데이터를 지원하지 않는다
Clojure는 동시성을 염두에둔 가변 데이터를 지원
(원자, 에이전트, STM)
원자
user=> (def my-atom (atom 42)) ; 원자 정의
#’user/my-atom
user=> (deref my-atom) ; 값 조회
42
user=> @my-atom ; 값 조회
42
user=> (swap! my-atom inc) ; 원자에 inc 함수 적용
43
user=> (swap! my-atom + 2) ; 원자에 + 함수 적용
45
user=> (reset! my-atom 0) ; 원자의 값을 변경
0
예제: 멀티스레딩
(def players (atom ())) ; 원자 players 정의
(defn list-players []
(response (json/encode @players))) ; players를 조회
(defn create-player [player-name]
(swap! players conj player-name) ; 새로운 player 추가
(status (response "") 201))
(defroutes app-routes
(GET "/players" [] (list-players))
(PUT "/players/:player-name" [player-name] (create-player player-name)))
(defn -main [& args]
(run-jetty (site app-routes) {:port 3000}))
players를 json으로 변환하는중
새로운 player를 추가된다면?
클로저의 자료구조는 영속적 속성을 가지므로 스레드에 안전
클로저의 영속성 자료구조
• 여기서 영속성은 불변성과 유사한 의미
• 값이 변경 되었을때 이전 값을 유지
user=> (def listv1 (list 1 2 3))
#’user/listv1
user=> listv1
(1 2 3)
; 새로운 항목 추가
user=> (def listv2 (cons 4 listv1))
#’user/listv2
user=> listv2
(4 1 2 3)
{:age 45, :name "paul"}
user=> mapv2
{:age 45, :name "paul", :sex :male}
Persistent data structures behave as though a complete copy is made each
time they’re modified. If that were how they were actually implemented, they
would be very inefficient and therefore of limited use (like CopyOnWriteArrayList,
which we saw in Copy on Write, on page 34). Happily, the implementation is
much more clever than that and makes use of structure sharing.
The easiest persistent data structure to understand is the list. Here’s a simple
list:
user=> (def listv1 (list 1 2 3))
#'user/listv1
user=> listv1
(1 2 3)
And here’s a diagram of what it looks like in memory:
1 2 3
listv1
Now let’s create a modified version with cons, which returns a copy of the list
with an item added to the front:
user=> (def listv2 (cons 4 listv1))
#'user/listv2
user=> listv2
(4 1 2 3)
The new list can share all of the previous list—no copying necessary:
1 2 3
listv1
4
listv2
Finally, let’s create another modified version:
Persistent data structures behave as though a complete copy is made each
time they’re modified. If that were how they were actually implemented, they
would be very inefficient and therefore of limited use (like CopyOnWriteArrayList,
which we saw in Copy on Write, on page 34). Happily, the implementation is
much more clever than that and makes use of structure sharing.
The easiest persistent data structure to understand is the list. Here’s a simple
list:
user=> (def listv1 (list 1 2 3))
#'user/listv1
user=> listv1
(1 2 3)
And here’s a diagram of what it looks like in memory:
1 2 3
listv1
Now let’s create a modified version with cons, which returns a copy of the list
with an item added to the front:
user=> (def listv2 (cons 4 listv1))
#'user/listv2
user=> listv2
(4 1 2 3)
The new list can share all of the previous list—no copying necessary:
1 2 3
listv1
4
listv2
Finally, let’s create another modified version:
report erratumwww.it-ebooks.info
리스트 전체가 아닌 일부만 사용하는 경우
복사를 통해 영속성 보장
user=> (def listv1 (list 1 2 3 4))
#’user/listv1
user=> (def listv2 (take 2 listv1))
#'user/listv2
user=> listv2
(1 2)
5
listv3
In this instance, the new list only makes use of part of the original, but
copying is still not necessary.
We can’t always avoid copying. Lists handle only common tails well—if we
want to have two lists with different tails, we have no choice but to copy.
Here’s an example:
user=> (def listv1 (list 1 2 3 4))
#'user/listv1
user=> (def listv2 (take 2 listv1))
#'user/listv2
user=> listv2
(1 2)
This leads to the following in memory:
1 2 3
listv1
4
1 2
listv2
All of Clojure’s collections are persistent. Persistent vectors, maps, and sets
are more complex to implement than lists, but for our purposes all we need
to know is that they share structure and that they provide similar performance
bounds to their nonpersistent equivalents in languages like Ruby and Java.
rwww.it-ebooks.info
명령형 언어에서 변수(Identity) 는
변화하는 값(상태)을 가지지만,
클로저에서 한 번 상태는 변하지 않음
영속성 보장
원자 etc.
• 재시도
• 내부적으로 Java AtomicReference의 compareAndSet 메서드를
사용함으로 재시도가 발생할 수 있음
• 함수형 코드의 특성상 부작용이 생기지 않음
• 확인자 및 감시자
user=> (def non-negative (atom 0 :validator #(>= % 0))) ; 확인자
user=> (reset! non-negative -1)
IllegalStateException Invalid reference state
user=> (def a (atom 0))
user=> (add-watch a :print #(println "Changed from " %3 " to " %4)) ; 감시자
user=> (swap! a + 2)
Changed from 0 to 2
에이전트
user=> (def my-agent (agent 0)) ; 에이전트 정의
user=> @my-agent ; 값 조회
0
user=> (send my-agent inc) ; 에이전트에 inc 함수 적용
user=> @my-agent
1
user=> (send my-agent + 2) ; 에이전트에 + 함수 적용
user=> @my-agent
3
• 원자와의 차이점: send
• 에이전트의 값이 변하기 전에 바로 리턴 됨
• 동작이 완료되기를 기다리기
• 에러 처리
에이전트 etc.
user=> (def my-agent (agent 0))

#'user/my-agent

user=> (send my-agent #((Thread/sleep 2000) (inc %)))

user=> (await my-agent) ; 동작이 완료되기를 기다림

nil

user=> @my-agent

1
user=> (def non-negative (agent 0 :validator (fn [new-val] (>= new-val 0)))) ; 확인자 정의
user=> (send non-negative dec) ; -1이 되어 실패 상태가 됨.
user=> @non-negative 

0
user=> (send non-negative inc) ; 실패 상태에서는 값 변경 안됨
IllegalStateException Invalid reference state clojure.lang.ARef.validate...
user=> (agent-error non-negative) ; 에러 내용 조회
#<IllegalStateException java.lang.IllegalStateException: Invalid reference state>
user=> (restart-agent non-negative 0) ; 에이전트 다시 시작
user=> (agent-error non-negative)
nil
예제: 인메모리 로그
(def log-entries (agent [])) ; 로그 수집을 위한 Agent
(defn log [entry]
(send log-entries conj [(now) entry])) ; agent로 로그 전송
logger.core=> (log "Something happened”)
#<Agent@bd99597: [[1366822537794 "Something happened”]]>
logger.core=> (log "Something else happened”)
#<Agent@bd99597: [[1366822538932 "Something happened”]]>
logger.core=> @log-entries
[[1366822537794 "Something happened"] [1366822538932 "Something else happened"]]
• ref를 정의하고, 트랜잭션 내에서만 변경 가능
트랜잭션 메모리(STM)
user=> (def my-ref (ref 0)) ; ref 정의
user=> @my-ref
0
user=> (ref-set my-ref 42) ; ref 값 설정 시도
IllegalStateException No transaction running
user=> (alter my-ref inc) ; ref 함수 적용 시도
IllegalStateException No transaction running
user=> (dosync (ref-set my-ref 42)) ; 트랜잭션 실행 (dosync)
user=> @my-ref
42
user=> (dosync (alter my-ref inc))
user=> @my-ref
43
STM은 3가지 트랜잭션 속성을 지원
원자성(Atomic)
일관성(Consistent)
고립성(Isolated)
지속성(Durability) 지원 안함
트랜잭션 재시도
• 트랜잭션이 모순되는 변경을 감지할 경우 재시도
• 에이전트 SEND는 트랙잭션이 성공할 경우에만 호출이 됨.
(def attempts (atom 0)) ; 재시도 횟수 기록
(def transfers (agent 0)) ; 전송 횟수 기록
(defn transfer [from to amount]
(dosync
(swap! attempts inc) // Side-effect
(send transfers inc)
(alter from - amount)
(alter to + amount)))
(def checking (ref 10000))
(def savings (ref 20000))
(defn stress-thread [from to iterations amount]

(Thread. #(dotimes [_ iterations] (transfer from to amount))))
(defn -main [& args]
(println "Before: Checking =" @checking " Savings =" @savings)
(let [t1 (stress-thread checking savings 100 100)
t2 (stress-thread savings checking 200 100)]
(.start t1) (.start t2) (.join t1) (.join t2))
(await transfers)
(println "Attempts: " @attempts) ; 300 이상
(println "Transfers: " @transfers) ; 300
(println "After: Checking =" @checking " Savings =" @savings))
예제: STM을 이용한 철학자
(def philosophers (into [] (repeatedly 5 #(ref :thinking)))) ; 5명의 철학자 정의
(defn think [] (Thread/sleep (rand 1000)))
(defn eat [] (Thread/sleep (rand 1000)))
(defn philosopher-thread [n]
(Thread. #(let [philosopher (philosophers n)
left (philosophers (mod (- n 1) 5)) ; 왼쪽 철학자
right (philosophers (mod (+ n 1) 5))] ; 오른쪽 철학자
(while true (think)
(when (claim-chopsticks philosopher left right) (eat) ; 양쪽 철학자 검사
(release-chopsticks philosopher))))))
(defn -main [& args]
(let [threads (map philosopher-thread (range 5))]
(doseq [thread threads] (.start thread))
(doseq [thread threads] (.join thread))))
(defn release-chopsticks [philosopher]
(dosync (ref-set philosopher :thinking)))
(defn claim-chopsticks [philosopher left right]
(dosync
(when (and (= @left :thinking) (= @right :thinking))
(ref-set philosopher :eating))))
; 클로저의 STM은 서로 다른 트랜잭션이 동일한 ref를 겹쳐서 변경하지 않도록 보장
; 위의 경우 다른 ref를 참조함으로, 인접한 철학자가 동시에 식사 가능
; 이를 막기위해 ensure 사용, ref의 리턴 값이 다른 트랜잭션에서 변경되지 않았음을 보장
(defn claim-chopsticks [philosopher left right]
(dosync
(when (and (= (ensure left) :thinking) (= (ensure right) :thinking))
(ref-set philosopher :eating))))
예제: 원자를 이용한 철학자
(def philosophers (atom (into [] (repeat 5 :thinking)))) ; 5명의 철학자 리스트를 원자로 생성

(defn philosopher-thread [philosopher]
(Thread. #(let [left (mod (- philosopher 1) 5) right (mod (+ philosopher 1) 5)]
(while true (think)
(when (claim-chopsticks! philosopher left right)
(eat)
(release-chopsticks! philosopher))))))
(defn release-chopsticks! [philosopher]
(swap! philosophers assoc philosopher :thinking))
(defn claim-chopsticks! [philosopher left right]
(swap! philosophers
(fn [ps] (if (and (= (ps left) :thinking) (= (ps right) :thinking))
(assoc ps philosopher :eating) ps))) ; 해당 철학자의 값을 설정후 원자에
(= (@philosophers philosopher) :eating))
STM vs. 원자
STM: 여러 값에 대해 조절되는 변경을 가능하게 함
원자: 단일 값에 대한 독립적인 변경을 보장
STM 해법을 원자로 바꾸는 것은 어렵지 않게 가능
가변 데이터의 최소 사용을 위해 원자의 사용을 권장
정리
• 동시성 관점에서의 클로저의 장단점
• 장점: 함수형 언어이지만, 이를 벗어나는 해법도 제공
• 단점: 분산 프로그래밍을 지원하지 않음
References
•Paul Butcher, 7가지 동시성 모델(임백준 옮김). 서울
시 마포구 양화로 한빛미디어, 2016.

More Related Content

What's hot

Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Circulus
 
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료욱진 양
 
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Young-Beom Rhee
 
Learning Node Book, Chapter 5
Learning Node Book, Chapter 5Learning Node Book, Chapter 5
Learning Node Book, Chapter 5Ji Hun Kim
 
[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)NAVER D2
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises우영 주
 
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow정연 최
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdfHyosang Hong
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개beom kyun choi
 
track2 04. MS는 Rx를 왜 만들었을까? feat. RxJS/ 네이버, 김훈민
track2 04. MS는 Rx를 왜 만들었을까? feat. RxJS/ 네이버, 김훈민 track2 04. MS는 Rx를 왜 만들었을까? feat. RxJS/ 네이버, 김훈민
track2 04. MS는 Rx를 왜 만들었을까? feat. RxJS/ 네이버, 김훈민 양 한빛
 
Promise 패턴 공부
Promise 패턴 공부Promise 패턴 공부
Promise 패턴 공부HongGun Yoo
 
일단 시작하는 코틀린
일단 시작하는 코틀린일단 시작하는 코틀린
일단 시작하는 코틀린Park JoongSoo
 
프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기Jongwook Choi
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰beom kyun choi
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기Yongha Yoo
 
프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oopYoung-Beom Rhee
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)beom kyun choi
 

What's hot (20)

Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체Startup JavaScript 4 - 객체
Startup JavaScript 4 - 객체
 
골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료골때리는 자바스크립트 발표자료
골때리는 자바스크립트 발표자료
 
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
 
Learning Node Book, Chapter 5
Learning Node Book, Chapter 5Learning Node Book, Chapter 5
Learning Node Book, Chapter 5
 
javascript02
javascript02javascript02
javascript02
 
[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdf
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
 
track2 04. MS는 Rx를 왜 만들었을까? feat. RxJS/ 네이버, 김훈민
track2 04. MS는 Rx를 왜 만들었을까? feat. RxJS/ 네이버, 김훈민 track2 04. MS는 Rx를 왜 만들었을까? feat. RxJS/ 네이버, 김훈민
track2 04. MS는 Rx를 왜 만들었을까? feat. RxJS/ 네이버, 김훈민
 
Promise 패턴 공부
Promise 패턴 공부Promise 패턴 공부
Promise 패턴 공부
 
Java8 람다
Java8 람다Java8 람다
Java8 람다
 
일단 시작하는 코틀린
일단 시작하는 코틀린일단 시작하는 코틀린
일단 시작하는 코틀린
 
프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기프로그래밍 대회: C++11 이야기
프로그래밍 대회: C++11 이야기
 
ES6-02
ES6-02ES6-02
ES6-02
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기
 
프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop프론트엔드스터디 E05 js closure oop
프론트엔드스터디 E05 js closure oop
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 

Viewers also liked

실무로 배우는 시스템 성능 최적화 Ch8
실무로 배우는 시스템 성능 최적화 Ch8실무로 배우는 시스템 성능 최적화 Ch8
실무로 배우는 시스템 성능 최적화 Ch8HyeonSeok Choi
 
HTTP 완벽가이드 21장
HTTP 완벽가이드 21장HTTP 완벽가이드 21장
HTTP 완벽가이드 21장HyeonSeok Choi
 
실무로 배우는 시스템 성능 최적화 Ch7
실무로 배우는 시스템 성능 최적화 Ch7실무로 배우는 시스템 성능 최적화 Ch7
실무로 배우는 시스템 성능 최적화 Ch7HyeonSeok Choi
 
실무로 배우는 시스템 성능 최적화 Ch6
실무로 배우는 시스템 성능 최적화 Ch6실무로 배우는 시스템 성능 최적화 Ch6
실무로 배우는 시스템 성능 최적화 Ch6HyeonSeok Choi
 
HTTP 완벽가이드 16장
HTTP 완벽가이드 16장HTTP 완벽가이드 16장
HTTP 완벽가이드 16장HyeonSeok Choi
 
Elastic search 클러스터관리
Elastic search 클러스터관리Elastic search 클러스터관리
Elastic search 클러스터관리HyeonSeok Choi
 
하둡완벽가이드 Ch9
하둡완벽가이드 Ch9하둡완벽가이드 Ch9
하둡완벽가이드 Ch9HyeonSeok Choi
 
Java 초보자를 위한 hadoop 설정
Java 초보자를 위한 hadoop 설정Java 초보자를 위한 hadoop 설정
Java 초보자를 위한 hadoop 설정HyeonSeok Choi
 
실무로배우는시스템성능최적화 Ch1
실무로배우는시스템성능최적화 Ch1실무로배우는시스템성능최적화 Ch1
실무로배우는시스템성능최적화 Ch1HyeonSeok Choi
 
HTTP 완벽가이드 6장.
HTTP 완벽가이드 6장.HTTP 완벽가이드 6장.
HTTP 완벽가이드 6장.HyeonSeok Choi
 
실무로 배우는 시스템 성능 최적화 8부 - 1,2,3장
실무로 배우는 시스템 성능 최적화 8부 - 1,2,3장실무로 배우는 시스템 성능 최적화 8부 - 1,2,3장
실무로 배우는 시스템 성능 최적화 8부 - 1,2,3장Sunggon Song
 
HTTP 완벽가이드 1장.
HTTP 완벽가이드 1장.HTTP 완벽가이드 1장.
HTTP 완벽가이드 1장.HyeonSeok Choi
 
7가지 동시성 모델 - 6장. 순차 프로세스 통신
7가지 동시성 모델 - 6장. 순차 프로세스 통신7가지 동시성 모델 - 6장. 순차 프로세스 통신
7가지 동시성 모델 - 6장. 순차 프로세스 통신Hyunsoo Jung
 
Logstash, ElasticSearch, Kibana
Logstash, ElasticSearch, KibanaLogstash, ElasticSearch, Kibana
Logstash, ElasticSearch, KibanaHyeonSeok Choi
 

Viewers also liked (20)

실무로 배우는 시스템 성능 최적화 Ch8
실무로 배우는 시스템 성능 최적화 Ch8실무로 배우는 시스템 성능 최적화 Ch8
실무로 배우는 시스템 성능 최적화 Ch8
 
HTTP 완벽가이드 21장
HTTP 완벽가이드 21장HTTP 완벽가이드 21장
HTTP 완벽가이드 21장
 
DDD Repository
DDD RepositoryDDD Repository
DDD Repository
 
Bounded Context
Bounded ContextBounded Context
Bounded Context
 
DDD Start Ch#3
DDD Start Ch#3DDD Start Ch#3
DDD Start Ch#3
 
실무로 배우는 시스템 성능 최적화 Ch7
실무로 배우는 시스템 성능 최적화 Ch7실무로 배우는 시스템 성능 최적화 Ch7
실무로 배우는 시스템 성능 최적화 Ch7
 
HTTPS
HTTPSHTTPS
HTTPS
 
실무로 배우는 시스템 성능 최적화 Ch6
실무로 배우는 시스템 성능 최적화 Ch6실무로 배우는 시스템 성능 최적화 Ch6
실무로 배우는 시스템 성능 최적화 Ch6
 
HTTP 완벽가이드 16장
HTTP 완벽가이드 16장HTTP 완벽가이드 16장
HTTP 완벽가이드 16장
 
Elastic search 클러스터관리
Elastic search 클러스터관리Elastic search 클러스터관리
Elastic search 클러스터관리
 
하둡완벽가이드 Ch9
하둡완벽가이드 Ch9하둡완벽가이드 Ch9
하둡완벽가이드 Ch9
 
Java 초보자를 위한 hadoop 설정
Java 초보자를 위한 hadoop 설정Java 초보자를 위한 hadoop 설정
Java 초보자를 위한 hadoop 설정
 
실무로배우는시스템성능최적화 Ch1
실무로배우는시스템성능최적화 Ch1실무로배우는시스템성능최적화 Ch1
실무로배우는시스템성능최적화 Ch1
 
HTTP 완벽가이드 6장.
HTTP 완벽가이드 6장.HTTP 완벽가이드 6장.
HTTP 완벽가이드 6장.
 
실무로 배우는 시스템 성능 최적화 8부 - 1,2,3장
실무로 배우는 시스템 성능 최적화 8부 - 1,2,3장실무로 배우는 시스템 성능 최적화 8부 - 1,2,3장
실무로 배우는 시스템 성능 최적화 8부 - 1,2,3장
 
HTTP 완벽가이드 1장.
HTTP 완벽가이드 1장.HTTP 완벽가이드 1장.
HTTP 완벽가이드 1장.
 
7가지 동시성 모델 - 6장. 순차 프로세스 통신
7가지 동시성 모델 - 6장. 순차 프로세스 통신7가지 동시성 모델 - 6장. 순차 프로세스 통신
7가지 동시성 모델 - 6장. 순차 프로세스 통신
 
Logstash, ElasticSearch, Kibana
Logstash, ElasticSearch, KibanaLogstash, ElasticSearch, Kibana
Logstash, ElasticSearch, Kibana
 
Pair RDD - Spark
Pair RDD - SparkPair RDD - Spark
Pair RDD - Spark
 
Learning spark ch1-2
Learning spark ch1-2Learning spark ch1-2
Learning spark ch1-2
 

Similar to 7가지 동시성 모델 4장

김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019min woog kim
 
파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304Yong Joon Moon
 
코딩테스트 합격자 되기 2주차 스터디 - 리스트_딕셔너리
코딩테스트 합격자 되기 2주차 스터디 - 리스트_딕셔너리코딩테스트 합격자 되기 2주차 스터디 - 리스트_딕셔너리
코딩테스트 합격자 되기 2주차 스터디 - 리스트_딕셔너리ultrasuperrok
 
R 기초 : R Basics
R 기초 : R BasicsR 기초 : R Basics
R 기초 : R BasicsYoonwhan Lee
 
R 프로그래밍 기본 문법
R 프로그래밍 기본 문법R 프로그래밍 기본 문법
R 프로그래밍 기본 문법Terry Cho
 
Data Mining with R CH1 요약
Data Mining with R CH1 요약Data Mining with R CH1 요약
Data Mining with R CH1 요약Sung Yub Kim
 
Python Programming: Function
Python Programming: FunctionPython Programming: Function
Python Programming: FunctionChan Shik Lim
 
파이썬정리 20160130
파이썬정리 20160130파이썬정리 20160130
파이썬정리 20160130Yong Joon Moon
 
스칼라와 스파크 영혼의 듀오
스칼라와 스파크 영혼의 듀오스칼라와 스파크 영혼의 듀오
스칼라와 스파크 영혼의 듀오Taeoh Kim
 
동기화, 스케줄링
동기화, 스케줄링동기화, 스케줄링
동기화, 스케줄링xxbdxx
 
MongoDB 하루만에 끝내기
MongoDB 하루만에 끝내기MongoDB 하루만에 끝내기
MongoDB 하루만에 끝내기Seongkuk Park
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229Yong Joon Moon
 
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++KWANGIL KIM
 
Multithread programming 20151206_서진택
Multithread programming 20151206_서진택Multithread programming 20151206_서진택
Multithread programming 20151206_서진택JinTaek Seo
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기지수 윤
 

Similar to 7가지 동시성 모델 4장 (20)

Clojure Chapter.6
Clojure Chapter.6Clojure Chapter.6
Clojure Chapter.6
 
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
 
파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304
 
코딩테스트 합격자 되기 2주차 스터디 - 리스트_딕셔너리
코딩테스트 합격자 되기 2주차 스터디 - 리스트_딕셔너리코딩테스트 합격자 되기 2주차 스터디 - 리스트_딕셔너리
코딩테스트 합격자 되기 2주차 스터디 - 리스트_딕셔너리
 
Clojure Monad
Clojure MonadClojure Monad
Clojure Monad
 
R 기초 : R Basics
R 기초 : R BasicsR 기초 : R Basics
R 기초 : R Basics
 
R 시작해보기
R 시작해보기R 시작해보기
R 시작해보기
 
R 프로그래밍 기본 문법
R 프로그래밍 기본 문법R 프로그래밍 기본 문법
R 프로그래밍 기본 문법
 
Data Mining with R CH1 요약
Data Mining with R CH1 요약Data Mining with R CH1 요약
Data Mining with R CH1 요약
 
Python Programming: Function
Python Programming: FunctionPython Programming: Function
Python Programming: Function
 
Node.js at OKJSP
Node.js at OKJSPNode.js at OKJSP
Node.js at OKJSP
 
파이썬정리 20160130
파이썬정리 20160130파이썬정리 20160130
파이썬정리 20160130
 
스칼라와 스파크 영혼의 듀오
스칼라와 스파크 영혼의 듀오스칼라와 스파크 영혼의 듀오
스칼라와 스파크 영혼의 듀오
 
동기화, 스케줄링
동기화, 스케줄링동기화, 스케줄링
동기화, 스케줄링
 
MongoDB 하루만에 끝내기
MongoDB 하루만에 끝내기MongoDB 하루만에 끝내기
MongoDB 하루만에 끝내기
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229
 
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++
 
Multithread programming 20151206_서진택
Multithread programming 20151206_서진택Multithread programming 20151206_서진택
Multithread programming 20151206_서진택
 
Spring Boot 2
Spring Boot 2Spring Boot 2
Spring Boot 2
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
 

More from HyeonSeok Choi

밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05HyeonSeok Choi
 
밑바닥부터시작하는딥러닝 Ch2
밑바닥부터시작하는딥러닝 Ch2밑바닥부터시작하는딥러닝 Ch2
밑바닥부터시작하는딥러닝 Ch2HyeonSeok Choi
 
프로그래머를위한선형대수학1.2
프로그래머를위한선형대수학1.2프로그래머를위한선형대수학1.2
프로그래머를위한선형대수학1.2HyeonSeok Choi
 
알고리즘 중심의 머신러닝 가이드 Ch04
알고리즘 중심의 머신러닝 가이드 Ch04알고리즘 중심의 머신러닝 가이드 Ch04
알고리즘 중심의 머신러닝 가이드 Ch04HyeonSeok Choi
 
딥러닝 제대로시작하기 Ch04
딥러닝 제대로시작하기 Ch04딥러닝 제대로시작하기 Ch04
딥러닝 제대로시작하기 Ch04HyeonSeok Choi
 
밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05HyeonSeok Choi
 
데이터 과학 입문 13장
데이터 과학 입문 13장데이터 과학 입문 13장
데이터 과학 입문 13장HyeonSeok Choi
 
데이터 과학 입문 5장
데이터 과학 입문 5장데이터 과학 입문 5장
데이터 과학 입문 5장HyeonSeok Choi
 
대용량아키텍처와성능튜닝 8장성능엔지니어링정의와범위
대용량아키텍처와성능튜닝 8장성능엔지니어링정의와범위대용량아키텍처와성능튜닝 8장성능엔지니어링정의와범위
대용량아키텍처와성능튜닝 8장성능엔지니어링정의와범위HyeonSeok Choi
 

More from HyeonSeok Choi (12)

밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05
 
밑바닥부터시작하는딥러닝 Ch2
밑바닥부터시작하는딥러닝 Ch2밑바닥부터시작하는딥러닝 Ch2
밑바닥부터시작하는딥러닝 Ch2
 
프로그래머를위한선형대수학1.2
프로그래머를위한선형대수학1.2프로그래머를위한선형대수학1.2
프로그래머를위한선형대수학1.2
 
알고리즘 중심의 머신러닝 가이드 Ch04
알고리즘 중심의 머신러닝 가이드 Ch04알고리즘 중심의 머신러닝 가이드 Ch04
알고리즘 중심의 머신러닝 가이드 Ch04
 
딥러닝 제대로시작하기 Ch04
딥러닝 제대로시작하기 Ch04딥러닝 제대로시작하기 Ch04
딥러닝 제대로시작하기 Ch04
 
밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05밑바닥부터시작하는딥러닝 Ch05
밑바닥부터시작하는딥러닝 Ch05
 
Cluster - spark
Cluster - sparkCluster - spark
Cluster - spark
 
Elastic search 검색
Elastic search 검색Elastic search 검색
Elastic search 검색
 
Erlang
ErlangErlang
Erlang
 
데이터 과학 입문 13장
데이터 과학 입문 13장데이터 과학 입문 13장
데이터 과학 입문 13장
 
데이터 과학 입문 5장
데이터 과학 입문 5장데이터 과학 입문 5장
데이터 과학 입문 5장
 
대용량아키텍처와성능튜닝 8장성능엔지니어링정의와범위
대용량아키텍처와성능튜닝 8장성능엔지니어링정의와범위대용량아키텍처와성능튜닝 8장성능엔지니어링정의와범위
대용량아키텍처와성능튜닝 8장성능엔지니어링정의와범위
 

7가지 동시성 모델 4장

  • 1. Separating Identity from State (The Clojure Way) 아꿈사 Cecil
  • 2. 목 차 • 원자(Atom) • Agent(에이전트) • STM(Software Transaction Memory) • 원자와 STM의 비교
  • 3. 순수 함수형 언어는 가변 데이터를 지원하지 않는다 Clojure는 동시성을 염두에둔 가변 데이터를 지원 (원자, 에이전트, STM)
  • 4. 원자 user=> (def my-atom (atom 42)) ; 원자 정의 #’user/my-atom user=> (deref my-atom) ; 값 조회 42 user=> @my-atom ; 값 조회 42 user=> (swap! my-atom inc) ; 원자에 inc 함수 적용 43 user=> (swap! my-atom + 2) ; 원자에 + 함수 적용 45 user=> (reset! my-atom 0) ; 원자의 값을 변경 0
  • 5. 예제: 멀티스레딩 (def players (atom ())) ; 원자 players 정의 (defn list-players [] (response (json/encode @players))) ; players를 조회 (defn create-player [player-name] (swap! players conj player-name) ; 새로운 player 추가 (status (response "") 201)) (defroutes app-routes (GET "/players" [] (list-players)) (PUT "/players/:player-name" [player-name] (create-player player-name))) (defn -main [& args] (run-jetty (site app-routes) {:port 3000})) players를 json으로 변환하는중 새로운 player를 추가된다면? 클로저의 자료구조는 영속적 속성을 가지므로 스레드에 안전
  • 6. 클로저의 영속성 자료구조 • 여기서 영속성은 불변성과 유사한 의미 • 값이 변경 되었을때 이전 값을 유지 user=> (def listv1 (list 1 2 3)) #’user/listv1 user=> listv1 (1 2 3) ; 새로운 항목 추가 user=> (def listv2 (cons 4 listv1)) #’user/listv2 user=> listv2 (4 1 2 3) {:age 45, :name "paul"} user=> mapv2 {:age 45, :name "paul", :sex :male} Persistent data structures behave as though a complete copy is made each time they’re modified. If that were how they were actually implemented, they would be very inefficient and therefore of limited use (like CopyOnWriteArrayList, which we saw in Copy on Write, on page 34). Happily, the implementation is much more clever than that and makes use of structure sharing. The easiest persistent data structure to understand is the list. Here’s a simple list: user=> (def listv1 (list 1 2 3)) #'user/listv1 user=> listv1 (1 2 3) And here’s a diagram of what it looks like in memory: 1 2 3 listv1 Now let’s create a modified version with cons, which returns a copy of the list with an item added to the front: user=> (def listv2 (cons 4 listv1)) #'user/listv2 user=> listv2 (4 1 2 3) The new list can share all of the previous list—no copying necessary: 1 2 3 listv1 4 listv2 Finally, let’s create another modified version: Persistent data structures behave as though a complete copy is made each time they’re modified. If that were how they were actually implemented, they would be very inefficient and therefore of limited use (like CopyOnWriteArrayList, which we saw in Copy on Write, on page 34). Happily, the implementation is much more clever than that and makes use of structure sharing. The easiest persistent data structure to understand is the list. Here’s a simple list: user=> (def listv1 (list 1 2 3)) #'user/listv1 user=> listv1 (1 2 3) And here’s a diagram of what it looks like in memory: 1 2 3 listv1 Now let’s create a modified version with cons, which returns a copy of the list with an item added to the front: user=> (def listv2 (cons 4 listv1)) #'user/listv2 user=> listv2 (4 1 2 3) The new list can share all of the previous list—no copying necessary: 1 2 3 listv1 4 listv2 Finally, let’s create another modified version: report erratumwww.it-ebooks.info
  • 7. 리스트 전체가 아닌 일부만 사용하는 경우 복사를 통해 영속성 보장 user=> (def listv1 (list 1 2 3 4)) #’user/listv1 user=> (def listv2 (take 2 listv1)) #'user/listv2 user=> listv2 (1 2) 5 listv3 In this instance, the new list only makes use of part of the original, but copying is still not necessary. We can’t always avoid copying. Lists handle only common tails well—if we want to have two lists with different tails, we have no choice but to copy. Here’s an example: user=> (def listv1 (list 1 2 3 4)) #'user/listv1 user=> (def listv2 (take 2 listv1)) #'user/listv2 user=> listv2 (1 2) This leads to the following in memory: 1 2 3 listv1 4 1 2 listv2 All of Clojure’s collections are persistent. Persistent vectors, maps, and sets are more complex to implement than lists, but for our purposes all we need to know is that they share structure and that they provide similar performance bounds to their nonpersistent equivalents in languages like Ruby and Java. rwww.it-ebooks.info
  • 8. 명령형 언어에서 변수(Identity) 는 변화하는 값(상태)을 가지지만, 클로저에서 한 번 상태는 변하지 않음 영속성 보장
  • 9. 원자 etc. • 재시도 • 내부적으로 Java AtomicReference의 compareAndSet 메서드를 사용함으로 재시도가 발생할 수 있음 • 함수형 코드의 특성상 부작용이 생기지 않음 • 확인자 및 감시자 user=> (def non-negative (atom 0 :validator #(>= % 0))) ; 확인자 user=> (reset! non-negative -1) IllegalStateException Invalid reference state user=> (def a (atom 0)) user=> (add-watch a :print #(println "Changed from " %3 " to " %4)) ; 감시자 user=> (swap! a + 2) Changed from 0 to 2
  • 10. 에이전트 user=> (def my-agent (agent 0)) ; 에이전트 정의 user=> @my-agent ; 값 조회 0 user=> (send my-agent inc) ; 에이전트에 inc 함수 적용 user=> @my-agent 1 user=> (send my-agent + 2) ; 에이전트에 + 함수 적용 user=> @my-agent 3 • 원자와의 차이점: send • 에이전트의 값이 변하기 전에 바로 리턴 됨
  • 11. • 동작이 완료되기를 기다리기 • 에러 처리 에이전트 etc. user=> (def my-agent (agent 0))
 #'user/my-agent
 user=> (send my-agent #((Thread/sleep 2000) (inc %)))
 user=> (await my-agent) ; 동작이 완료되기를 기다림
 nil
 user=> @my-agent
 1 user=> (def non-negative (agent 0 :validator (fn [new-val] (>= new-val 0)))) ; 확인자 정의 user=> (send non-negative dec) ; -1이 되어 실패 상태가 됨. user=> @non-negative 
 0 user=> (send non-negative inc) ; 실패 상태에서는 값 변경 안됨 IllegalStateException Invalid reference state clojure.lang.ARef.validate... user=> (agent-error non-negative) ; 에러 내용 조회 #<IllegalStateException java.lang.IllegalStateException: Invalid reference state> user=> (restart-agent non-negative 0) ; 에이전트 다시 시작 user=> (agent-error non-negative) nil
  • 12. 예제: 인메모리 로그 (def log-entries (agent [])) ; 로그 수집을 위한 Agent (defn log [entry] (send log-entries conj [(now) entry])) ; agent로 로그 전송 logger.core=> (log "Something happened”) #<Agent@bd99597: [[1366822537794 "Something happened”]]> logger.core=> (log "Something else happened”) #<Agent@bd99597: [[1366822538932 "Something happened”]]> logger.core=> @log-entries [[1366822537794 "Something happened"] [1366822538932 "Something else happened"]]
  • 13. • ref를 정의하고, 트랜잭션 내에서만 변경 가능 트랜잭션 메모리(STM) user=> (def my-ref (ref 0)) ; ref 정의 user=> @my-ref 0 user=> (ref-set my-ref 42) ; ref 값 설정 시도 IllegalStateException No transaction running user=> (alter my-ref inc) ; ref 함수 적용 시도 IllegalStateException No transaction running user=> (dosync (ref-set my-ref 42)) ; 트랜잭션 실행 (dosync) user=> @my-ref 42 user=> (dosync (alter my-ref inc)) user=> @my-ref 43
  • 14. STM은 3가지 트랜잭션 속성을 지원 원자성(Atomic) 일관성(Consistent) 고립성(Isolated) 지속성(Durability) 지원 안함
  • 15. 트랜잭션 재시도 • 트랜잭션이 모순되는 변경을 감지할 경우 재시도 • 에이전트 SEND는 트랙잭션이 성공할 경우에만 호출이 됨. (def attempts (atom 0)) ; 재시도 횟수 기록 (def transfers (agent 0)) ; 전송 횟수 기록 (defn transfer [from to amount] (dosync (swap! attempts inc) // Side-effect (send transfers inc) (alter from - amount) (alter to + amount))) (def checking (ref 10000)) (def savings (ref 20000)) (defn stress-thread [from to iterations amount]
 (Thread. #(dotimes [_ iterations] (transfer from to amount)))) (defn -main [& args] (println "Before: Checking =" @checking " Savings =" @savings) (let [t1 (stress-thread checking savings 100 100) t2 (stress-thread savings checking 200 100)] (.start t1) (.start t2) (.join t1) (.join t2)) (await transfers) (println "Attempts: " @attempts) ; 300 이상 (println "Transfers: " @transfers) ; 300 (println "After: Checking =" @checking " Savings =" @savings))
  • 16. 예제: STM을 이용한 철학자 (def philosophers (into [] (repeatedly 5 #(ref :thinking)))) ; 5명의 철학자 정의 (defn think [] (Thread/sleep (rand 1000))) (defn eat [] (Thread/sleep (rand 1000))) (defn philosopher-thread [n] (Thread. #(let [philosopher (philosophers n) left (philosophers (mod (- n 1) 5)) ; 왼쪽 철학자 right (philosophers (mod (+ n 1) 5))] ; 오른쪽 철학자 (while true (think) (when (claim-chopsticks philosopher left right) (eat) ; 양쪽 철학자 검사 (release-chopsticks philosopher)))))) (defn -main [& args] (let [threads (map philosopher-thread (range 5))] (doseq [thread threads] (.start thread)) (doseq [thread threads] (.join thread))))
  • 17. (defn release-chopsticks [philosopher] (dosync (ref-set philosopher :thinking))) (defn claim-chopsticks [philosopher left right] (dosync (when (and (= @left :thinking) (= @right :thinking)) (ref-set philosopher :eating)))) ; 클로저의 STM은 서로 다른 트랜잭션이 동일한 ref를 겹쳐서 변경하지 않도록 보장 ; 위의 경우 다른 ref를 참조함으로, 인접한 철학자가 동시에 식사 가능 ; 이를 막기위해 ensure 사용, ref의 리턴 값이 다른 트랜잭션에서 변경되지 않았음을 보장 (defn claim-chopsticks [philosopher left right] (dosync (when (and (= (ensure left) :thinking) (= (ensure right) :thinking)) (ref-set philosopher :eating))))
  • 18. 예제: 원자를 이용한 철학자 (def philosophers (atom (into [] (repeat 5 :thinking)))) ; 5명의 철학자 리스트를 원자로 생성
 (defn philosopher-thread [philosopher] (Thread. #(let [left (mod (- philosopher 1) 5) right (mod (+ philosopher 1) 5)] (while true (think) (when (claim-chopsticks! philosopher left right) (eat) (release-chopsticks! philosopher)))))) (defn release-chopsticks! [philosopher] (swap! philosophers assoc philosopher :thinking)) (defn claim-chopsticks! [philosopher left right] (swap! philosophers (fn [ps] (if (and (= (ps left) :thinking) (= (ps right) :thinking)) (assoc ps philosopher :eating) ps))) ; 해당 철학자의 값을 설정후 원자에 (= (@philosophers philosopher) :eating))
  • 19. STM vs. 원자 STM: 여러 값에 대해 조절되는 변경을 가능하게 함 원자: 단일 값에 대한 독립적인 변경을 보장 STM 해법을 원자로 바꾸는 것은 어렵지 않게 가능 가변 데이터의 최소 사용을 위해 원자의 사용을 권장
  • 20. 정리 • 동시성 관점에서의 클로저의 장단점 • 장점: 함수형 언어이지만, 이를 벗어나는 해법도 제공 • 단점: 분산 프로그래밍을 지원하지 않음
  • 21. References •Paul Butcher, 7가지 동시성 모델(임백준 옮김). 서울 시 마포구 양화로 한빛미디어, 2016.