Kevin Kostlan
Kevin Kostlan

Reputation: 3519

Clojure reset(ing) multiple atoms at once

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

Answers (2)

Alex
Alex

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

Nathan Davis
Nathan Davis

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 atoms cannot be updated atomically.

You can combine both items into a single atom. But you also may want to consider refs, 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

Related Questions