简体   繁体   English

Clojure原子的竞争条件

[英]Race condition with Clojure atom

I apparently do not understand clojure's atom correctly. 我显然不正确理解clojure的原子。 I thought that it's atomicity guarantee could be demonstrated as follows: 我认为它的原子性保证可以证明如下:

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

Unfortunately this is not the case. 不幸的是,这种情况并非如此。 The code seems to exhibit a race condition on the set contained in the users atom. 代码似乎在users atom中包含的集合上显示竞争条件。

Which data structure do I need to use to make sure that all users are successfully added to the users set? 我需要使用哪种数据结构来确保所有用户都成功添加到用户集中?

SOLUTION

As pointed out in the comments, there were several bugs in the code. 正如评论中指出的那样,代码中存在一些错误。 The main bug was not using dorun to force the evaluation of all of the futures. 主要的错误是没有使用dorun来强制评估所有的期货。 After making this change, the code runs as expected: 进行此更改后,代码按预期运行:

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

See Clojure Atom documentation . 请参阅Clojure Atom文档

Also from Joy of Clojure: 同样来自Clojure的Joy:

Atoms are like Refs in that they're synchronous but are like Agents in that they're independent (uncoordinated). 原子就像Refs,因为它们是同步的,但就像Agent一样,它们是独立的(不协调的)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM