0

我显然不正确理解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"))
4

1 回答 1

2

请参阅Clojure Atom 文档

同样来自 Clojure 的喜悦:

Atom 与 Ref 相似,因为它们是同步的,但与 Agent 相似,它们是独立的(不协调的)。

于 2013-02-13T05:54:51.657 回答