Clojure一次重置(多个)原子

时间:2015-08-20 16:40:38

标签: concurrency clojure thread-safety

假设foo和bar是原子。

; consistent.
(reset! foo x)
; inconsistent x and y combination.
(reset! bar y)
; consistent.

是否可以立即重置它们,以便没有其他线程可以看到这种不一致?或者是否有必要将x和y捆绑成一个原子,而不是让x和y本身就是原子?

2 个答案:

答案 0 :(得分:4)

对于多个引用的协调更新,您希望使用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和{{的一致视图1}}。

使用STM存在开销,因此使用协调引用与封装所有可变状态的单个原子的选择将取决于您的确切用法。

答案 1 :(得分:3)

Clojure website's page on atoms(强调添加):

  

Atoms提供了一种管理共享,同步,独立状态的方法。

这意味着每个atom彼此独立,因此无法以原子方式更新一组atom

您可以将这两个项目合并为一个atom。但您也可以考虑refs,它提供多个项目的交易更新:

  

事务引用(Refs)确保通过软件事务内存(STM)安全共享使用可变存储位置