2011-04-20 200 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)))