Browse Clojure Foundations for Java Developers

Atoms

Atoms are Clojure’s go-to for synchronous, independent state: atomic updates with swap! and reset! (think AtomicReference).

Atoms manage independent, synchronous state changes. If you’re coming from Java, an atom is closest to an AtomicReference<T> with a functional update operation.

Use an atom when:

  • the state is owned by one “thing” (a cache, stats counter, in-memory registry)
  • updates don’t need to coordinate with other pieces of state
  • you want atomicity without locks

Create and Read

1(def counter (atom 0))
2
3@counter        ; deref => 0
4(deref counter) ; same as @

Update: reset! and swap!

1(reset! counter 100)     ; set a new value
2(swap!  counter inc)     ; apply a function to the current value
3(swap!  counter + 5)     ; functions can take extra args

Important: swap! Functions Should Be Pure

Under contention, swap! may retry the update function. If you do side effects inside it (logging, DB calls, HTTP), you can accidentally repeat them.

Compare-and-Set

1(compare-and-set! counter 105 0) ; => true/false

Knowledge Check: Atoms

### Why should the function passed to `swap!` avoid side effects? - [x] Because it may be retried under contention, which could repeat the side effect. - [ ] Because atoms only work at compile time. - [ ] Because `swap!` runs actions on a separate thread. - [ ] Because atoms can’t hold maps or vectors. > **Explanation:** `swap!` uses CAS semantics. Under contention, the update function may be invoked multiple times before one update wins. ### What does `@counter` do? - [x] Dereferences the atom to obtain its current value. - [ ] Resets the atom to `nil`. - [ ] Increments the atom. - [ ] Creates a new atom. > **Explanation:** `@x` is shorthand for `(deref x)`. It works for atoms, refs, agents, futures, delays, and promises. ### What’s the difference between `reset!` and `swap!`? - [x] `reset!` sets an explicit value; `swap!` computes a new value from the old via a function. - [ ] `swap!` is read-only, but `reset!` mutates. - [ ] `reset!` is asynchronous, but `swap!` is synchronous. - [ ] They are synonyms. > **Explanation:** `swap!` is the common “update based on current value” operation. `reset!` replaces the value directly.
Revised on Friday, April 24, 2026