Use atoms for independent state updates via swap! and keep the updates pure.
An atom is a reference to an immutable value. The value can change over time, but each change is an atomic “swap to a new value.”
The most important habit is: update an atom by providing a pure function.
1(def counter (atom 0))
2
3(swap! counter inc) ;; => 1
4@counter ;; => 1
Under the hood, swap! is CAS-style: if another thread updates the atom concurrently, Clojure retries your function with the new value. That is why the function must be free of side effects.
Java mental model: atom updates are like
AtomicInteger.updateAndGet, but generalized to any value (often a map).