All topics
library
advanced

Atomic Classes & CAS Operations

Use lock-free thread-safe operations on single variables with AtomicInteger, AtomicReference, and compare-and-swap.

An atomic class updates a single variable safely without a lock, using one CPU instruction.

CAS = trying to swap a book on a shelf. You check if 'Java Basics' is still there (expected), grab it, and put 'Java Advanced' in its place (newValue). If someone already swapped it, you notice and try again.

Key Concepts

1
    AtomicInteger count = new AtomicInteger();
    count.incrementAndGet();         // atomic, lock-free
2
Why count++ is not enough. It is three operations — read, add, write — and two threads interleaving them lose an update. synchronized fixes it by excluding one thread; CAS fixes it by retrying.
count++synchronized
3
Compare-and-set is the primitive underneath.
    int old, next;
    do {
      old = count.get();
      next = old * 2;
    } while (!count.compareAndSet(old, next));
4
compareAndSet(expected, new) writes only if the value is still expected. If another thread changed it, the call returns false and you loop. No thread ever blocks.
compareAndSet(expected, new)expected
5
The classes.
    AtomicInteger, AtomicLong      counters, sequence numbers
    AtomicBoolean                  a one-shot flag
    AtomicReference<T>             swap an object reference
    AtomicIntegerArray             per-element atomics
    LongAdder, LongAccumulator     high-contention counters
6
updateAndGet saves writing the loop:
    count.updateAndGet(n -> n * 2);
    ref.updateAndGet(cfg -> cfg.withTimeout(5));
updateAndGet
7
Versus synchronized.
    no context switch -- a failed CAS retries instead of parking
    no deadlock, because nothing is held
    but it busy-spins, so heavy contention burns CPU
synchronized
8
LongAdder is the answer to that spin. It keeps a cell per contending thread and sums them on sum(), so threads rarely collide. Under a dozen threads hammering a counter it is dramatically faster than AtomicLong — at the cost of an approximate read while writes are in flight.
LongAddersum()AtomicLong
9
The ABA problem is the subtle one. A value goes A to B and back to A; your CAS sees A, succeeds, and misses that anything happened. It matters when the value is a reference whose identity carries meaning:
10
    AtomicStampedReference<Node>     pairs the value with a counter
11
And the scope limit. CAS protects one variable. Two fields that must change together still need a lock, or an immutable object swapped atomically through an AtomicReference.
AtomicReference
12
What the interviewer is probing.1. "Why is count++ unsafe even on a volatile int?" Probing: the visibility and atomicity split. Stalls: "Volatile makes it atomic." Moves up: it is read-modify-write, three operations; volatile gives visibility, not atomicity. Use AtomicInteger or a lock.
13
2. "How does compareAndSet work?" Probing: the primitive under the class. Stalls: "It locks briefly." Moves up: a CPU instruction writes only if the value still matches what you read; if another thread changed it, the call returns false and you retry — nothing blocks.
14
3. "What is the ABA problem?" Probing: the subtle failure of CAS. Stalls: "Never heard of it." Moves up: a value goes A to B and back to A, so your CAS succeeds having missed that anything happened; AtomicStampedReference pairs the value with a counter.
15
4. "When is LongAdder better than AtomicLong?" Probing: contention. Stalls: "They are the same." Moves up: under heavy contention — it keeps a cell per thread and sums on read, so threads rarely collide, at the cost of an approximate read mid-flight.