Atomic classes vs volatile vs synchronized — how do you c… — Cracked Java
// Concurrency & Multithreading · Atomics & Compare-And-Swap
MidTheory

Atomic classes vs volatile vs synchronized — how do you choose?

Pick by the operation you need: volatile for visibility of a single read or write, atomics for a lock-free read-modify-write on one variable, and synchronized (or an explicit lock) when you must keep multiple variables or steps consistent as one unit. They form a ladder of increasing power and cost.

What each one guarantees

  • volatile — visibility and ordering for a single field. A write is seen by later reads, and it prevents reordering. It does not make compound operations atomic: volatile int x; x++ is still read-modify-write and races.
  • Atomic classes — visibility plus atomic compound updates on one variable via CAS. incrementAndGet, compareAndSet, updateAndGet are atomic and lock-free.
  • synchronized — mutual exclusion over an arbitrary block, so you can keep several fields invariant together. It also gives visibility (lock release/acquire is a happens-before edge), at the cost of blocking and possible contention/deadlock.

The decision

// 1. volatile: a flag written by one thread, read by others
private volatile boolean running = true;   // just visibility

// 2. atomic: lock-free counter, single variable
private final AtomicInteger hits = new AtomicInteger();
hits.incrementAndGet();                    // atomic read-modify-write

// 3. synchronized: TWO fields must stay consistent together
private double balance;
private List<String> ledger = new ArrayList<>();
synchronized void withdraw(double amt) {   // multi-step invariant
    balance -= amt;
    ledger.add("withdraw " + amt);
}

The bank-transfer case is the giveaway that atomics are not enough: debiting one account and crediting another must be one atomic unit across two variables — no single CAS covers that, so you need a lock.

Cost ordering

Roughly cheapest to most expensive: plain read < volatile < uncontended CAS < contended CAS < uncontended lock < contended lock (which can deschedule the thread). Reach for the weakest tool that is correct — but never trade correctness for speed.

Mark your status