Browse Clojure Foundations for Java Developers

Refs and Transactions

Refs use Software Transactional Memory (STM) for coordinated, synchronous updates to multiple pieces of shared state.

Refs are for coordinated, synchronous state changes across multiple values. Clojure’s STM (Software Transactional Memory) lets you update multiple refs as one atomic transaction—without explicit locks.

Use refs when:

  • you must update multiple pieces of state together (invariants across refs)
  • you want atomicity and consistency across those updates

Create and Read

1(def checking (ref 100))
2(def savings  (ref 200))
3
4@checking ; => 100

Update with dosync + alter

All ref updates must happen inside a transaction:

1(dosync
2  (alter checking - 10)
3  (alter savings  + 10))

If the transaction conflicts with another transaction, it may be retried automatically.

ref-set and commute

  • ref-set replaces the ref’s value (still inside dosync).
  • commute is an optimization for commutative updates (like adding to a counter) where the STM can reorder safely.

Important: Avoid Side Effects Inside dosync

Because transactions can retry, doing I/O inside dosync can repeat side effects.

The common pattern is:

  • compute the new values transactionally
  • perform side effects (logging, I/O) outside the transaction using the committed result

Knowledge Check: Refs / STM

### What is the main purpose of refs? - [x] Coordinated, atomic updates across multiple pieces of shared state. - [ ] Fast indexed access to data. - [ ] Asynchronous background work. - [ ] Java class loading. > **Explanation:** Use refs when you need to update multiple related values together and preserve invariants. ### Why should you avoid side effects inside `dosync`? - [x] Because the transaction may retry, which could repeat the side effect. - [ ] Because refs don’t allow calling functions. - [ ] Because `dosync` runs only at compile time. - [ ] Because STM disables exceptions. > **Explanation:** Retries are a feature of STM conflict resolution. Side effects inside a retried transaction can run multiple times. ### Which function is commonly used to update a ref inside a transaction? - [x] `alter` - [ ] `swap!` - [ ] `reset!` - [ ] `send` > **Explanation:** `alter` changes a ref’s value within a `dosync` transaction. `swap!`/`reset!` are atom operations; `send` is for agents.
Revised on Friday, April 24, 2026