When several threads update shared state, locks can turn a small change into a deadlock puzzle. An atom offers a simpler alternative: it coordinates updates without explicit locks, while immutable data keeps reads safe because each read observes a consistent snapshot. section 8.0 section 8.1
An atom exposes three focused operations:
- get returns the current value. section 8.2
- set overwrites the current value. section 8.2
- swap receives a function, computes a new value, and updates the atom only when its observed state is still current. section 8.2
From counters to whole-system state
A thread-safe counter initializes an atom with zero, increments it through swap(x => x + 1), and reads it through get. The same pattern handles an immutable string-map cache: swap receives the old cache and returns a new cache containing the result. For larger state, commit can wrap reconciliation inside swap so concurrent updates retry instead of racing through consistency logic. The trade-off is worth watching: thousands of threads repeatedly swapping one atom could theoretically starve, although ordinary follow-up work gives other threads opportunities to proceed. section 8.2 section 8.3 section 8.4 section 8.5
Listing 8.3 Implementation of the Atom class
class Atom {
state;
constructor() {}
get() {
return this.state;
}
set(state) {
this.state = state;
}
swap(f) {
while(true) {
var stateSnapshot = this.state;
var nextState = f(stateSnapshot);
if (!atomicCompareAndSet(this.state,
stateSnapshot,
nextState)) { #1
continue;
}
return nextState;
}
}
}
Inspect the compact Atom implementation: swap snapshots the state, computes the next state, and retries when atomic comparison-and-set detects a competing update. section 8.2

