Clojure 一次重置多个原子

Kev*_*lan 1 concurrency clojure thread-safety

假设 foo 和 bar 是原子。

; consistent.
(reset! foo x)
; inconsistent x and y combination.
(reset! bar y)
; consistent.
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*lex 5

对于多个引用的协调更新,您需要使用refs而不是atom。Refs 只能在事务内部修改,Clojure 的 STM(软件事务内存)确保在提交事务之前对 refs 的所有操作都成功,因此事务外的所有线程都会看到一致的 refs 视图。

 (def foo (ref :x))
 (def bar (ref :y))
 (dosync
    (ref-set foo :x1)
    (ref-set bar :y1))
Run Code Online (Sandbox Code Playgroud)

dosync在此示例中,如果另一个线程中的事务修改了任一 ref,则将重试事务(由 描述),以确保其他线程看到foo和的一致视图bar

使用 STM 会产生开销,因此选择使用协调引用还是封装所有可变状态的单个原子将取决于您的具体使用情况。