Browse Learn Clojure Foundations as a Java Developer

Create and Read Atoms

Create Clojure atoms for independent in-process state, read them safely with deref, and design the stored value as immutable data rather than a mutable Java object.

An atom is a reference to one current value. The atom can point to a newer value over time, but the value itself should be ordinary immutable Clojure data.

That distinction matters for Java engineers. In Java, mutable state often hides behind object fields and setter methods. In Clojure, an atom makes the changing identity explicit and keeps the domain rules in functions that transform data.

Basic Operations

Operation What it does Java comparison
(atom value) Creates a new atom holding value. new AtomicReference<>(value)
@state Reads the current value. ref.get()
(deref state) Same read, written as a function call. ref.get()
(swap! state f) Replaces the value with (f old-value). updateAndGet style update
(reset! state v) Replaces the value directly. set, but on the atom reference
1(def service
2  (atom {:status :starting
3         :requests 0}))
4
5@service
6;; => {:status :starting, :requests 0}
7
8(get @service :status)
9;; => :starting

The map is not mutated. A later update will produce a different map, and the atom will point to that newer map.

Choose the Atom Boundary

The atom should usually sit at a boundary: application lifecycle state, a small in-memory cache, a metrics snapshot, or a REPL-managed development system. Do not wrap every nested field in its own atom.

Design choice Consequence
One atom holding a related map Updates can preserve invariants inside that map.
Many tiny atoms for related facts Readers may observe combinations that never existed logically.
Atom holding immutable data Safe reads and functional updates.
Atom holding a mutable Java object Atomic reference replacement does not make the object internals safe.

If two facts must always change together, prefer one immutable aggregate in one atom, or use refs if they are genuinely separate identities.

Reads Are Snapshots

Reading an atom gives you the current value at that instant. Another thread may update the atom immediately after your read. That is normal; design code so a read value is a stable snapshot, not a lock.

1(defn service-ready? []
2  (= :ready (:status @service)))

This function answers a question about one observed value. It does not prevent later updates.

Java Migration Notes

Java habit Clojure adjustment
Add synchronized getters and setters. Prefer a small atom plus pure update functions.
Store mutable collections behind an atomic reference. Store persistent Clojure maps, vectors, or sets.
Spread state across many fields. Group facts by invariant and update boundary.
Read a value and then mutate it in place. Use swap! to compute a replacement value.

Knowledge Check

### What does reading an atom with `@service` return? - [x] The atom's current value at that instant. - [ ] A lock that blocks all other threads. - [ ] A mutable copy of the atom. - [ ] A transaction that can update several refs. > **Explanation:** Dereferencing an atom returns the current value. It does not lock the atom or protect later logic from concurrent updates. ### Why is an atom usually paired with immutable data? - [x] The atom controls reference replacement, while immutable values stay safe to share. - [ ] Atoms can only hold numbers. - [ ] Immutable data prevents all allocation. - [ ] Immutable data turns the atom into durable storage. > **Explanation:** The atom is the changing identity. The values it points to should be safe snapshots, which is why persistent Clojure data structures fit so well. ### What is a warning sign that one atom is not enough? - [x] Several separate identities must be updated consistently together. - [ ] The value is a Clojure map. - [ ] The atom is read with `@`. - [ ] The namespace has more than one function. > **Explanation:** Atoms coordinate one independent identity. If the invariant spans several identities, consider one aggregate value or refs.
Revised on Saturday, May 23, 2026