【问题标题】:Why does swap! try again even when an Atom's value hasn't changed?为什么要换!即使 Atom 的值没有改变,也要重试?
【发布时间】:2018-10-27 22:24:14
【问题描述】:

假设我有以下一段(人为的)Clojure 代码:

(def c (clojure.lang.Atom. [nil nil]))
(swap! c 
   (fn [[x y]] 
       ["done", (second (swap! c (fn [[x y]] [x y])))]))

我希望它的工作方式如下:

  1. Clojure 将c 拆箱以找到[nil nil],并将其传递给外部fn

  2. 外部fn 调用swap!,后者将c 拆箱以找到[nil nil],并将此值传递给内部fn

  3. 内部fn 返回[nil nil]。对swap! 的内部调用将其替换为c 的新值。

  4. 外层fn返回值["done" nil]

  5. 外层swap!尝试compare-and-set!,发现c的当前值[nil nil]和旧值[nil nil]一样,所以成功,换入["done" nil]

但事实上,这段代码永远循环:外层循环不断重试。

这是为什么?我的心智模型缺少什么?

【问题讨论】:

    标签: concurrency clojure


    【解决方案1】:

    Clojure Slack 上的几个人帮助我了解了这里发生的事情(谢谢!)。 compare-and-set! 使用 identical?(即 Java 引用相等)来比较原子的新旧值。每次我重新创建向量[x y] 时,我都在创建一个新对象,而不是旧对象的identical?。尽管我不认为内部 swap! 会发生任何变异,但从技术上讲确实如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-06
      • 1970-01-01
      • 2021-11-25
      • 2019-01-20
      • 2020-01-02
      • 2015-03-25
      • 1970-01-01
      相关资源
      最近更新 更多