Concurrency
Atomics & Nonblocking Synchronization
Atomic classes turn compare-and-swap (CAS) — the CPU's optimistic "update if unchanged" instruction — into lock-free counters, references, and accumulators. Faster than locks under contention you can measure, and immune to deadlock.
- CAS: atomically "set to new if still expected"; on failure, loop and retry
AtomicInteger/Long/Reference= volatile semantics + atomic read-modify-write- For hot counters,
LongAdderbeatsAtomicLong— it stripes contention across cells updateAndGet/accumulateAndGetrun a lambda atomically (must be pure — it may retry)- ABA problem: value changed A→B→A looks unchanged;
AtomicStampedReferenceversions it - Nonblocking algorithms are library-author territory; using atomics is everyday code
public class CasCounter {
private final AtomicLong value = new AtomicLong();
public long increment() {
long current;
do {
current = value.get();
} while (!value.compareAndSet(current, current + 1)); // retry on interference
return current + 1;
}
}Locks are pessimistic (assume conflict, exclude everyone); CAS is optimistic (assume no conflict, detect and retry). Under low-to-moderate contention the retry loop almost never retries and costs one CPU instruction — no parking, no context switch, no priority inversion, no deadlock (JCiP ch. 15). Under extreme contention, CAS retries burn CPU — that's LongAdder's cue.
private final LongAdder requests = new LongAdder(); // hot counter: stripes cells
requests.increment();
long total = requests.sum(); // slightly weak snapshot — fine for stats
private final AtomicReference<Config> config = new AtomicReference<>(initial);
config.updateAndGet(c -> c.withTimeout(t)); // atomic functional update
AtomicIntegerArray slots = new AtomicIntegerArray(64); // per-element atomicity