2011-04-20 4 views
4

이 코드는 http://www.learningclojure.com/2010/11/yet-another-way-to-write-factorial.html에 있지만, pop-task가 threadsafe가되어야하는 경우/이해하지 못합니다. 같은 머리를 두 번 돌려주는 것을 허용하지 않습니까?클로저에 쓰레드 안전 팝?

(DEF 할 일 목록 (원자 '()))
(defn이 추가 작업! [t] (스왑! 할 일 목록 # (단점 t %)))
(defn이 팝업 h])

만약 그렇다면, 원자를 계속 사용하고 피크를 쓰는 것이 가능합니까? (예 : [h (첫 번째 할 일 목록) 그리고 스왑! 원자 적으로, 또는 이것이 ref 메커니즘의 일입니까?

-

두 가지 좋은 답변에 감사드립니다.

답변

7

또는 낮은 수준으로 떨어집니다.

(def to-do-list (atom nil)) 

(defn add-task! 
    [t] 
    (swap! to-do-list conj t)) 

(defn pop-task! 
    [] 
    (let [[h & r :as l] @to-do-list] 
    (if (compare-and-set! to-do-list l r) 
     h 
     (recur)))) 
+0

할 일 목록에 더 복잡한 구조가 있고 특정 키에 대한 업데이트가 필요한지 궁금합니다. – Rustem

1

그래, 그 코드는 스레드로부터 안전하지 않습니다. 스왑을 사용하면 스레드로부터 안전하게 만들 수 있습니다! 원자의 새 값을 반환합니다. 이는 대기열을 "팝 된"값과 결합해야 함을 의미합니다.

(def to-do-list 
    (atom {})) 

(defn add-task! 
    [t] 
    (swap! to-do-list 
     (fn [tl] 
      {:queue (cons t (:queue tl))}))) 

(defn pop-task! 
    [] 
    (let [tl (swap! to-do-list 
        (fn [old] 
        {:val (first (:queue old)) 
        :queue (rest (:queue old))}))] 
    (:val tl)))