Reputation: 3519
Suppose foo and bar are atoms.
; consistent.
(reset! foo x)
; inconsistent x and y combination.
(reset! bar y)
; consistent.
Is it possible to reset them at once so that no other thread can see this inconsistency? Or is it necessary to bundle x and y into an atom instead of having x and y themselves being atoms?
Upvotes: 1
Views: 312
Reputation: 13941
For coordinated updates to multiple references, you want to use refs, not atoms. Refs can only be modified inside a transaction, and Clojure's STM (software transactional memory) ensures that all operations on refs succeed before committing the transaction, so all threads outside the transaction see a consistent view of the refs.
(def foo (ref :x))
(def bar (ref :y))
(dosync
(ref-set foo :x1)
(ref-set bar :y1))
In this example, the transaction (delineated by dosync
) will be retried if either ref was modified by a transaction in another thread, ensuring that other threads see a consistent view of foo
and bar
.
There is overhead in using STM, so the choice of using coordinated refs vs. a single atom that encapsulates all your mutable state will depend on your exact usage.
Upvotes: 5
Reputation: 5766
From the Clojure website's page on atoms (emphasis added):
Atoms provide a way to manage shared, synchronous, independent state.
This means that each atom
is independent of each other, and therefore a set of atom
s cannot be updated atomically.
You can combine both items into a single atom
. But you also may want to consider ref
s, which provide for transactional updates of multiple items:
transactional references (Refs) ensure safe shared use of mutable storage locations via a software transactional memory (STM)
Upvotes: 3