Clojure原子的竞争条件

Clojure原子的竞争条件,clojure,parallel-processing,race-condition,Clojure,Parallel Processing,Race Condition,我显然不能正确理解clojure的原子。我认为它的原子性保证可以证明如下: (def users (atom #{})) (defn add-user! [name] (swap! users (fn [users] (conj users name)))) (do (map deref [(future (add-user! "bob")) (future (add-user! "clair")) (future (add-user!

我显然不能正确理解clojure的原子。我认为它的原子性保证可以证明如下:

(def users (atom #{}))

(defn add-user! [name]
  (swap! users
    (fn [users]
      (conj users name))))

(do
  (map deref
    [(future (add-user! "bob"))
     (future (add-user! "clair"))
     (future (add-user! "ralph"))
     (future (add-user! "mark"))
     (future (add-user! "bill"))
     (future (add-user! "george"))]))

(println @users)
(println
  (if (= 5 (count @users))
    "SUCCESS!"
    "FAIL"))
不幸的是,情况并非如此。代码似乎在users atom中包含的集合上显示了竞争条件

我需要使用哪种数据结构来确保所有用户都成功添加到用户集

解决方案 正如评论中指出的,代码中有几个bug。主要的错误不是使用dorun强制评估所有的期货。进行此更改后,代码将按预期运行:

(def users (atom #{}))

(defn add-user! [name]
  (swap! users
    (fn [users]
      (conj users name))))

(dorun
  (map deref
    [(future (add-user! "bob"))
     (future (add-user! "clair"))
     (future (add-user! "ralph"))
     (future (add-user! "mark"))
     (future (add-user! "bill"))
     (future (add-user! "george"))]))

(println @users)
(println
  (if (= 6 (count @users))
    "SUCCESS!"
    "FAIL"))

同样来自Clojure的喜悦:

原子就像参考系一样,因为它们是同步的,但就像代理一样,因为它们是独立的(不协调的)


我不知道当你添加6个用户时为什么会期望5个用户。另外,
adduser
可以是
(swap!users conj name)
。回答自己的问题时,应该创建答案,而不是编辑问题。