liveBook · Manning

Atom

As explained in Clojure: The Essential Reference

clojure.lang.Atom is the Clojure runtime class that wraps a Java AtomicReference to implement atom state management.

An atom is a concurrency-aware reference for synchronous, uncoordinated changes to a single piece of state. Multiple threads can share it without explicit locking: each update derives a new value from the old value, retrying when another thread changes the state first. A Clojure atom is represented by clojure.lang.Atom, which wraps a Java AtomicReference. section 14.0 section 14.5

Choose the operation according to how the new state is determined:

  • Use swap! when the update depends on the current value. It accepts additional arguments and may invoke the update function repeatedly, so side effects inside that function are unsafe. section 14.5
  • Use reset! when the new value does not depend on the previous value. It does not retry; competing resets are resolved by the last operation to access the atom. section 14.5
  • Use compare-and-set! for an explicit conditional replacement: it succeeds only when the atom still contains the expected value. section 14.5

Updating an atom

Define an atom with (def a (atom 0)), increment it with (swap! a inc), and read the result with @a. The returned value is 1. For nested state, (swap! m update-in [:b :c] inc) updates a map directly and returns the revised map.

Bounded retry with CAS

A custom swap-or-bail! loop can read the current value, compute a candidate, and call compare-and-set!. If another thread intervenes, it retries a fixed number of times before reporting failure. This is useful when the update function is slow or retries must be bounded.

(def a (atom 0)) ; #1
(swap! a inc) ; #2
;; 1
@a ; #3
;; 1

Inspect the minimal lifecycle: create an atom, update it, and dereference its current value. section 14.5

How Clojure: The Essential Reference covers it

How deep it goes
Defines retrying updates, reset semantics, CAS behavior, dereferencing, and the AtomicReference wrapper through executable examples.
Examples
Uses counters, nested maps, configuration state, bounded CAS retries, and memoization caches.
What it assumes
Assumes familiarity with Clojure functions and references while contrasting explicit locking with persistent data structures.
What you can do after
Apply atom, swap!, reset!, compare-and-set!, and dereferencing to manage shared state.
How it connects
Relates atoms to persistent data structures, refs, agents, deref, validators, watchers, locking, and memoize.

Also explained in

Compare how 2 books explain atom →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.