【问题标题】:Clojure reset(ing) multiple atoms at onceClojure 一次重置(ing)多个原子
【发布时间】:2015-08-20 16:40:37
【问题描述】:
假设 foo 和 bar 是原子。
; consistent.
(reset! foo x)
; inconsistent x and y combination.
(reset! bar y)
; consistent.
是否可以一次重置它们以使其他线程无法看到这种不一致?或者是否有必要将 x 和 y 捆绑成一个原子,而不是让 x 和 y 本身就是原子?
【问题讨论】:
标签:
concurrency
clojure
thread-safety
【解决方案1】:
对于多个引用的协调更新,您希望使用refs,而不是原子。 refs 只能在事务内部修改,Clojure 的 STM(软件事务内存)确保在提交事务之前对 refs 的所有操作都成功,因此事务外的所有线程都可以看到 refs 的一致视图。
(def foo (ref :x))
(def bar (ref :y))
(dosync
(ref-set foo :x1)
(ref-set bar :y1))
在此示例中,如果任一 ref 被另一个线程中的事务修改,则事务(由 dosync 描述)将被重试,以确保其他线程看到 foo 和 bar 的一致视图。
使用 STM 存在开销,因此选择使用协调的 ref 还是使用封装所有可变状态的单个 atom 将取决于您的具体用法。
【解决方案2】:
来自Clojure website's page on atoms(强调添加):
Atom 提供了一种管理共享、同步、独立状态的方法。
这意味着每个atom是相互独立的,因此一组atoms不能被原子更新。
您可以将这两个项目合并为一个 atom。但您也可能需要考虑refs,它提供多个项目的事务更新:
事务引用 (Refs) 通过软件事务内存 (STM) 确保对可变存储位置的安全共享使用