Threadsafe поп в clojure? - PullRequest
       16

Threadsafe поп в clojure?

4 голосов
/ 20 апреля 2011

Я нашел этот код на http://www.learningclojure.com/2010/11/yet-another-way-to-write-factorial.html,, но я не понимаю, может ли / как поп-задача быть безопасной для потоков.Разве он не позволяет дважды возвращать одну и ту же голову?

(def to-do-list (atom '()))
(defn add-task! [T] (swap! To-do-list # (cons t%)))
(defn pop-task! [] (let [h (first @ to-do-list)] (swap! to-do-list rest) h))

Если это так, то можно ли продолжать использовать Atom, писать «peek» и «swap»!атомарно, или это работа для механизма ref?

-

Спасибо за два хороших ответа!

Ответы [ 2 ]

7 голосов
/ 20 апреля 2011

Или вы переходите на более низкий уровень.

(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))))
1 голос
/ 20 апреля 2011

Да, этот код не является потокобезопасным.Вы можете сделать его потокобезопасным, воспользовавшись тем, что своп!возвращает новое значение атома, что означает, что вам нужно объединить очередь с «всплывающим» значением.

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