我显然不正确理解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"))
不幸的是,这种情况并非如此。该代码似乎在用户原子中包含的集合上表现出竞争条件。
我需要使用哪种数据结构来确保所有用户都成功添加到用户集中?
解决方案
正如评论中指出的那样,代码中有几个错误。主要错误是没有使用 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"))