Clojure Chapter.6

1,237 views
1,132 views

Published on

2010년 아꿈사 스터디
http://cafe.naver.com/architect1
Clojure 6장

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,237
On SlideShare
0
From Embeds
0
Number of Embeds
280
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Clojure Chapter.6

  1. 1. Clojure 6장. Concurrency 아키텍트를 꿈꾸는 사람들 cafe.naver.com/architect1 현수명 soomong.net #soomong
  2. 2. 목차 병행성 공유된 자원 변수 만들기 실습 다른언어로 변수만들기 병행성 제어 Lib 4인방 ref , atom , agent , var Example – Snake Example – Lancet Erlang 의 병행성
  3. 3. 병행성? 여러가지를 동시에 일어나게 만드는 일
  4. 4. 병행성! 어렵지 않음. 여러색의Thread 나 Process 를 띄우면 되요 문제는, 동시에 일어나는 일들 즉 도화지의 변화하는 상태를 어떻게 제어할 것인가
  5. 5. 공유된 자원 공유된 자원? Clojure 에서 변수를 어떻게 만들지? 변수!
  6. 6. 변수 만들기 실습 (def X 5) #’user/X X 5 (def X 3) #’user/X (def ^{:user/comment "A"} x 5 ) (meta #’user/x) {:ns #<Namespace user>, :name x, :file "NO_SOURCE_PATH", :line 30, :user/comment "A"} (def x 3) (meta #’user/x) {:ns #<Namespace user>, :name x, :file "NO_SOURCE_PATH", :line 32}
  7. 7. 다른언어로 변수만들기 int x = 5; x = 3;
  8. 8. Clojure 에서는? 데이터의 상태가 기본적으로 변경불가능 Clojure 에는 직접 변경할수있는 변수 없음 But. 예외가 있음 코드에서 명백하게 선언해야한다는 조건하에 간접적으로 변경 가능한 병행성 API 들을 제공
  9. 9. 보통의 다른 언어들 모든 상태는 변경가능 상태변화가 코드전체에 뒤섞여 있음 병행성은Thread 로 구현 여러Thread 가 접근하는 경우 적절한 락을 통해 한번에 하나만 접근하도록 보호 int x = 5; x = 3;
  10. 10. 목차 병행성 공유된 자원 변수 만들기 실습 다른언어로 변수만들기 병행성 제어 Lib 4인방 ref , atom , agent , var Example – Snake Example – Lancet Erlang 의 병행성
  11. 11. 병행성 제어 Lib 4인방 ref + STM 제어 O 동기적 갱신 atom 제어 X 동기적 갱신 agent 제어 X 비동기적 갱신 var Thread 내부의 동적범위
  12. 12. ref (def amount 3) (ref amount) (deref amount) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IDeref (repl-1:33) (def ref_amount (ref amount)) #'user/ref_amount (deref ref_amount) 3 (alter ref_amount dec) java.lang.IllegalStateException: No transaction running (repl-1:40) ; 갱신할때 적절한 보호를 해주어야한다. ; Clojure 는 트랜잭션을 사용해서 보호 (dosync (alter ref_amount dec)) 2 Clojure 의 병행성 제어 Lib 1 API ref deref ref-set dosync alter commute :validator
  13. 13. Clojure 의 병행성 제어 Lib 1 API ref deref ref-set dosync alter commute :validator (def ref_amount (ref amount)) #'user/ref_amount (deref ref_amount) 3 (ref-set ref_amount (def size 5) java.lang.IllegalStateException: No transaction running ; 갱신할때 적절한 보호를 해주어야한다. ; Clojure 는 트랜잭션을 사용해서 보호 (dosync (ref-set ref_amount (def size 5)) #'user/size ref
  14. 14. Clojure 의 잠금 다른 언어에서는 데이터 보호를 위해 Lock 을 사용 Clojure 에서는 데이터 보호를 위해 Transaction 을 사용
  15. 15. STM Software Transaction Memory Atomicity 원자성 Consistency 일관성 Isolation 고립성 Durability 영구성 Database 는 ACID Clojure 는 ACI
  16. 16. ref Clojure 의 병행성 제어 Lib 1 API ref deref ref-set dosync alter commute :validator (def amount 3) (def ref_amount (ref amount)) #'user/ref_amount (def size 10) (def ref_size (ref size)) #'user/ref_size (dosync (ref-set ref_amount 6) (ref-set ref_size 20)) 20 ; 갱신이 하나의 트랜잭션 안에서 수행됨
  17. 17. ref Clojure 의 병행성 제어 Lib 1 API ref deref ref-set dosync alter commute :validator (defstruct message :sender :text) (struct message "stu" "testmsg") {:sender "stu", :text "testmsg"} (def messages (ref ())) #'user/messages (defn native-add-msg [msg] (dosync (ref-set messages (cons msg @messages)))) (defn add-msg [msg] (dosync (alter messages conj msg))) (add-msg (struct message "user1" "hello")) ({:sender "user1", :text "hello"}) (add-msg (struct message "user2" "hoho")) ({:sender "user2", :text "hoho"} {:sender "user1", :text "hello"})
  18. 18. ref Clojure 의 병행성 제어 Lib 1 API ref deref ref-set dosync alter commute :validator (defn add-msg-commute [msg] (dosync (commute messages conj msg))) ; 트랜잭션의 순서가 마음대로 재배열됨 (def validate-msg-list (partial every? #(and (:sender %) (:text %)))) (def messages (ref () :validator validate-msg-list)) ; 유효성 확인 추가 (add-message "not a valid msg") java.lang.IllegalStateException: Invalid reference state (add-message (struct message "stu" "good message")) ({:sender "stu", :text "good message"})
  19. 19. 병행성 제어 Lib 4인방 ref + STM 제어 O 동기적 갱신 atom 제어 X 동기적 갱신 agent 제어 X 비동기적 갱신 var Thread 내부의 동적범위
  20. 20. atom Clojure 의 병행성 제어 Lib 2 API atom reset! swap!(def amount 3) (def atom_amount (atom amount)) #'user/atom_amount (deref atom_amount) 3 (reset! atom_amount 0) 0 ; atom 은 트랜잭션 내에서 변경되는것이 아니기 때문에 ; dosync 를 사용할 필요 없음 ( 제어 X ) ; 동시에 2개의 atom 을 변경시키는것은 불가능! ; 이것이 ref 와의 차이점 (def atom_track (atom {:title "Hoot" :singer "SOSI"})) #'user/atom_track (swap! atom_track assoc :title "Huk")
  21. 21. 병행성 제어 Lib 4인방 ref + STM 제어 O 동기적 갱신 atom 제어 X 동기적 갱신 agent 제어 X 비동기적 갱신 var Thread 내부의 동적범위
  22. 22. agent Clojure 의 병행성 제어 Lib 3 API agent send await :validator clear-agent (def counter (agent 0)) #'user/counter (send counter inc) #<Agent@482d59a3: 1> ; 비동기적으로 갱신되므로 inc 를 나중에 처리한다 (deref counter) 1 ; 이값을 확인할때쯤이면 inc 는 이미 thread 풀에서 작업을 완료 ; dosync 를 사용할 필요 없음 ( 제어 X ) (await counter) ; agent 에 대한 작업완료시까지 현재 수행되는 thread 를 block
  23. 23. agent Clojure 의 병행성 제어 Lib 3 API agent send await :validator clear-agent-errors (def counter (agent 0 :validator number?)) #'user/counter (send counter (fn [_] "boo")) #<Agent@5dde45e2 FAILED: 0> ; 유효성 검사에서 실패 (agent-errors counter) (#<IllegalStateException java.lang.IllegalStateException: Invalid reference state>) (clear-agent-errors counter) 0
  24. 24. 병행성 제어 Lib 4인방 ref + STM 제어 O 동기적 갱신 atom 제어 X 동기적 갱신 agent 제어 X 비동기적 갱신 var Thread 내부의 동적범위
  25. 25. var Clojure 의 병행성 제어 Lib 4 API binding set! (def foo 10) #'user/foo foo 10 (.start (Thread. (fn [] (println foo)))) nil 10 (binding [foo 42] foo) 42 (defn print-foo [] (println foo)) (let [foo “let foo”] (print-foo)) 10 (binding [foo “bound foo”] (print-foo)) bound foo
  26. 26. var Clojure 의 병행성 제어 Lib 4 API binding set!(defn slow-double [n] (Thread/sleep 100) (* n 2)) (defn calls-slow-double [] (map slow-double [1 2 1 2 1 2])) (time (dorun (calls-slow-double))) "Elapsed time: 608.778399 msecs“ (defn demo-memoize [] (time (dorun (binding [slow-double (memoize slow-double)] (calls-slow-double))))) ; memoize 를 동적 바인딩으로 calls-slow-double 수정없이 교체! (demo-memoize) "Elapsed time: 202.116447 msecs"
  27. 27. 병행성 제어 Lib 4인방 ref + STM 제어 O 동기적 갱신 atom 제어 X 동기적 갱신 agent 제어 X 비동기적 갱신 var Thread 내부의 동적범위 Java lock 제어 O 동기적 갱신
  28. 28. Clojure 의 병행성 상태변화가 없는 함수형 모델 상태 변화가 존재하는 모델 병행성 API 를 사용하지 않은 부분 병행성API 를 사용한 부분
  29. 29. 목차 병행성 공유된 자원 변수 만들기 실습 다른언어로 변수만들기 병행성 제어 Lib 4인방 ref , atom , agent , var Example – Snake Example – Lancet Erlang 의 병행성
  30. 30. Example - Snake (defn reset-game [snake apple] (dosync (ref-set apple (create-apple)) (ref-set snake (create-snake))) nil) (defn update-direction [snake newdir] (when newdir (dosync (alter snake turn newdir)))) (defn update-positions [snake apple] (dosync (if (eats? @snake @apple) (do (ref-set apple (create-apple)) (alter snake move :grow)) (alter snake move))) nil)
  31. 31. Example - Lancet API locking ; START: create-runonce (defn create-runonce [function] (let [sentinel (Object.) result (atom sentinel)] (fn [& args] (locking sentinel (if (= @result sentinel) (reset! result (function)) @result))))) ; END: create-runonce
  32. 32. Erlang 의 병행성
  33. 33. 병행성 지향 프로그래밍 • Concurrency-oriented programming • 처음부터 병행성을 고려해서 만든 언어. • 공유 메모리가 없음 • 잠금 매커니즘 필요없음 • 쉽게 병행 프로그래밍 가능 Erlang
  34. 34. 단일 할당 변수 1> X. 1: variable ‘X' is unbound 2> X = 50. 50 3> X = 23. ** exception error: no match of right hand side value 23 • 변수가 아니라 write-once 변수 • 즉 한번만 bound 를 할 수 있음 Erlang
  35. 35. 패턴매칭 X = 50. • = 은 할당연산자가 아니라 패턴매칭연산 자. • 오른쪽을 평가해서 그 결과를 왼쪽에 있는 패턴과 매치하라는 뜻. Erlang
  36. 36. 왜 단일 할당이 프로그램을 더 낫게 만드는가? • 변수의 값을 바꿀수 있다? – 누가 언제 바꿨는지 깔끔하게 알기힘듬. – 복잡한 잠금 매커니즘 필요. • 변수의 값을 바꿀수 없다? – 불변상태의 메모리는 read 만 가능. – 잠금 매커니즘이 필요없다. • 즉 쉬운 병행 프로그래밍 가능 – 어떻게? 프로세스 메시지 전달 방식으로. Erlang
  37. 37. Pure message passing language • 순수 메시지 전달 언어 • 명령어 3개로 병행프로그래밍 가능 spawn : 프로세스 생성 ! (send) : 메시지 보내기 receive : 메시지 받기 Erlang
  38. 38. $ erl 1> Pid = spawn(fun area:loop/0). <0.45.0> 2> Pid ! {rect, 6, 10}. rect : 60 3> Pid ! {circle, 5}. circle : 78.5 4> Pid ! {triangle, 2, 4, 5}. what is it? triangle? Erlang
  39. 39. area.erl -module(area). -export([loop/0]). loop() -> receive {rect, Width, Ht} -> io:format(“rect : ~p~n”, [Width * Ht]), loop(); {circle, R} -> io:format(“circle : ~p~n”, [3.14 * R * R]), loop(); Other -> io:format(“what is it? ~p?~n”, [Other]), loop() end. Erlang
  40. 40. Reference Programming Clojure – 인사이트 병행성 색연필 http://www.flickr.com/photos/kayyali/5121460008/ http://www.flickr.com/photos/queensy/4630729220/ Programming Erlang - 인사이트
  41. 41. 감사합니다

×