2011-04-20 202 views
4

我在http://www.learningclojure.com/2010/11/yet-another-way-to-write-factorial.html上找到了這段代碼,但我不明白彈出式任務應該是/應該如何進行線程安全的。難道它不允許兩次返回同一個頭?clojure中的線程安全流行?

(DEF待辦事項列表(原子「()))
(DEFN添加任務![T](互換!待辦事項列表#(利弊T%)))
(DEFN流行-task![](let [h(first @ to-do-list)](swap!to-do-list rest)h))

如果是這樣,是否有可能繼續使用原子並編寫並交換!原子,或者這是裁判機制的工作?

-

感謝您的兩個很好的答案!

回答

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 2015-12-29 08:25:31

1

是的,該代碼不是線程安全的。您可以通過利用swap這一事實來使其線程安全!返回原子的新值,這意味着您需要將隊列與「彈出」值組合。

(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)))