Clojure 一次重置多个原子

Clojure reset(ing) multiple atoms at once

假设 foo 和 bar 是原子。

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

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

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

Atoms provide a way to manage shared, synchronous, independent state.

这意味着每个 atom 彼此独立,因此一组 atom 不能自动更新。

您可以将这两项合并为一项 atom。但您可能还想考虑 refs,它提供多个项目的事务更新:

transactional references (Refs) ensure safe shared use of mutable storage locations via a software transactional memory (STM)

对于多个引用的协调更新,您想使用 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 会产生开销,因此选择使用协调引用还是使用封装所有可变状态的单个原子将取决于您的确切用法。