Skip to content

[프로그래밍 클로저] 6장 병행성

Joony edited this page Aug 25, 2014 · 10 revisions

락의 문제 (lester.k)

ref와 소프트트웨어 트랜젝션 메모리리(STM) (lester.k)

joony 궁금한 것 임시 단락..;

184에서, track : 현실 세계 반영하려면 ref로 가르키는게 계속 변해야하는 것 아닌가? 그걸 refset에서 하는 구나.. ㅋㅋ 갑자기 composer..이건 또 왜 alter를 쓰는지 와닿지 않음!

제어가 필요없는 동기화된 갱신에 애텀 사용하기 (joony.l)

atom

(atom initial-state options?)
; option은 다음과 같읕 키/값 쌍으로 이뤄진다
; :validator validate-fn
; :meta metadata-map
  • ref는 공유되는 상태에 대한 접근을 제어할 필요가 있을 떄 유용하게 사용.
  • 공유되지 않는 데이터를 갱신하는 경우라면, 애텀을 사용하는 것이 낫다.
  • ref보다 가벼운 접근 방식.

위 예에서 ref대신 atom

(def current-track (atom "Venus, the Bringer of peace"))
-> #'user/current-track

; 값을 알아내는 것은 deref로 알아내듯 동일

(deref current-track)
-> "Venus, the Bringer of peace"

@current-track
-> "Venus, the Bringer of peace"

reset

(reset! an-atom newval)

애텀은 트랜잭션 내에서 변경되는 것이 아니기 때문에, dosync를 사용할 필요가 없다. 애텀의 값을 갱신하기 위해서는 reset!을 사용하면 그만.

(reset! current-track "Credo")

애텀을 사용하되 current-track과 current-composer가 동시에 변경되도록 할수 없다. 이게 ref와 atom의 차이이다. 값들이 동시에 갱신되도록 제어하려면 ref를 사용해야한다.

할 수 있는 방법이 있긴하지만, 이것은 문제를 모델링하는 방식을 바꾸는 경우에 한한다. 트랙 제목과 작곡가로 이루어진 맵을 만들고 한 atom에 저장하면 되지 않을까?

(def current-track (atom {:title "credo" :composer "Byrd"}))

(reset! current-track {:title "Spem in Alium" :composer "Tallis"})
-> {:title "Spem in Alium", :composer "Tallis"}	

swap!

작곡가는 그대로고, 트랙만 변경하고 싶다면?

(swap! an-atom f & args))

함수 f에 an-atom의 현재 값과 args들을 넘겨, 거기서 반환된 값으로 an-atom을 갱신한다.

swap!가 :title키에 대헤 assoc함수를 적용하도록 만들어서 트랙제목만 변경해보자

(swap! current-track assoc :title "Sancte Dues")
-> {:title "Sancte Dues", :composer "Tallis"}

swap!이 새로운 값을 반환한다. 만약 다른 스레드가 같은 atom의 값을 변경하려고 시도중이라면 swap은 재시도 된다. 따라서 swap!에 넘기는 함수는 부수효과를 가져선 안된다.

ref와 atom은 모두 동기화된 갱신을 위한 것. 갱신 함수가 값을 반환하는 시점에, ref나 atom이 가리키는 값 역시 갱신되어 있다. 값이 나중에 변경될 수도 있는 비동기적 갱신으로도 충분한 경우라면, 에이젼트를 사용하는 게 낫다.

비동기적 갱신을 위한 에이전트 (joony.l)

var를 이용해 스레드별 상태 관리하기 (todd.krause)