Clojure separates values (usually immutable data) from references (places where state can change).
Here are the core tools you will see in real projects:
- Var: a namespace-level reference (defined with
def/defn). Vars support redefinition at the REPL and can be dynamically bound in limited cases.
- Atom: independent, synchronous updates to a single value via
swap! (CAS-style).
- Ref: coordinated updates across multiple refs using STM transactions (
dosync + alter).
- Agent: asynchronous, serialized updates to an agent’s value via
send.
Java mental model: atoms feel like AtomicReference + “update with a function”; refs feel like transactional coordination; agents feel like a single-threaded work queue for state updates.
This section helps you choose a tool based on the kind of state and coordination your problem actually has.
In this section
-
Clojure Concurrency Primitives: Atoms, Refs, Agents, and Vars
Explore Clojure's concurrency primitives—atoms, refs, agents, and vars—and learn how they simplify state management in concurrent programming.
-
Atoms in Clojure: Managing State with Compare-and-Swap
Explore the concept of atoms in Clojure, a mechanism for managing synchronous, independent state changes using compare-and-swap operations. Learn how to create and update atoms safely without locks.
-
Clojure Refs and Software Transactional Memory (STM): A Guide for Java Developers
Explore Clojure's Refs and Software Transactional Memory (STM) for coordinated, synchronous state changes, and learn how STM simplifies concurrency management compared to traditional Java approaches.
-
Clojure Agents: Managing Asynchronous State Changes
Explore how Clojure agents facilitate asynchronous, independent state changes, allowing actions to be performed in the background without blocking the main thread. Learn to use `send` and `send-off` for dispatching actions to agents and retrieving their state with `deref`.
-
Vars in Clojure: Dynamic Bindings and Thread-Local State
Explore the concept of Vars in Clojure, focusing on their role in dynamic bindings and managing thread-local state for Java developers transitioning to Clojure.