Concurrencyhigh

CAS & AtomicInteger

Compare-And-Swap (CAS) is a CPU-level atomic instruction that updates a memory location only if it currently holds an expected value. Java's Atomic* classes (AtomicInteger, AtomicReference, etc.) expose CAS via compareAndSet().

Memory anchor

CAS = picking up the last donut: 'I see a glazed donut, I'll grab it -- but only if it's still glazed when my hand arrives.' If someone swapped it, you pull back and try again. ABA = someone replaced it with an identical donut.

Expected depth

AtomicInteger.incrementAndGet() uses CAS in a spin loop — read current value, compute new value, CAS; retry if CAS fails (another thread changed the value). This is lock-free but not wait-free (a thread can spin indefinitely under extreme contention). LongAdder (Java 8+) outperforms AtomicLong under high contention by striping the counter across cells and reducing CAS conflicts — use for metrics/counters. AtomicReference enables lock-free data structures. VarHandle (Java 9+) generalizes Unsafe-based atomics with type-safe access to fields and array elements.

Deep — senior internals

ABA problem: CAS succeeds even if the value was changed from A to B and back to A between the read and the CAS — the swap cannot detect this. AtomicStampedReference and AtomicMarkableReference add a stamp/mark to detect ABA. Non-blocking algorithms (Michael-Scott queue, CLH queue for locks) use CAS chains. Project Valhalla's value types will require rethinking CAS semantics since value objects have no identity. LongAdder's @Contended annotation on Cell padding fields prevents false sharing — each cell occupies its own cache line.

🎤Interview-ready answer

CAS is the foundation of all lock-free concurrency in Java — it atomically tests-and-sets a memory location using a single CPU instruction (CMPXCHG on x86). AtomicInteger wraps CAS in a retry loop for common operations. Under low contention it outperforms synchronized; under high contention, LongAdder is superior because it stripes state across cells. The ABA problem — where a value changes A→B→A and CAS falsely succeeds — requires AtomicStampedReference when object identity matters (e.g., lock-free stack pop).

Common trap

CAS spin-loops under high contention cause CPU waste and can be slower than a mutex — use LongAdder for high-frequency counter increments, not AtomicLong.incrementAndGet().