【问题标题】:swap! value in atom (nested-map) Clojure交换!原子中的值(嵌套映射)Clojure
【发布时间】:2017-04-17 16:39:35
【问题描述】:

我正在尝试从多个线程更新原子(映射)中的嵌套计数器,但得到不可预测的结果。

  (def a (atom {:id {:counter 0}}))

  (defn upvote [id]
    (swap! a assoc-in [(keyword id) :counter] (inc (get-in @a [(keyword id) :counter])))
  )

  (dotimes [i 10] (.start (Thread. (fn [] (upvote "id")))))
  (Thread/sleep 12000)
  (prn @a) 

我是 Clojure 的新手,所以很可能我做错了什么,但不知道是什么。它正在打印一个计数器值,结果从 4 到 10 不等,每次都不同。

我想自动更新计数器值,并希望这种方法总是给我一个计数器值 10。它只会在失败时重试并最终达到 10。

这是一个可以同时触发的投票功能。

你能看出我在这里做错了吗?

【问题讨论】:

  • 如果您不需要调用线程立即知道修改的结果,也可以考虑使用代理而不是原子。代理隐式序列化修改,因此您不必担心不同步。

标签: multithreading concurrency clojure


【解决方案1】:

您正在代码中以非原子方式更新原子。您首先通过@a 获取它的值,然后使用swap 函数应用它。该值可能会在两者之间发生变化。

更新值的原子方式是在swap中使用纯函数,而不是通过@引用之前的原子值:

(defn upvote [id]
  (swap! a update-in [(keyword id) :counter] inc))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多