Interview Prep Zoneby CuriouserLabs

Question 1 of 5 · staff level

Locks have to be built out of something. What hardware primitives make synchronization possible?

🎤 Say this first

You cannot build mutual exclusion from ordinary loads and stores on modern hardware (reordering + interleaving defeat every classroom algorithm). CPUs therefore provide atomic read-modify-write instructions — test-and-set, fetch-and-add, and the workhorse compare-and-swap (CAS: 'if memory still holds A, replace with B, atomically'). Every mutex, semaphore, AtomicInteger and lock-free queue bottoms out in these, plus memory barriers to constrain reordering. Atomics work by the core claiming the cache line exclusively (via coherence) for the duration — which is also why contended atomics are expensive: cache-line ping-pong.

The full picture

  • CAS in one line: CAS(addr, expected, new) returns success iff *addr == expected and swaps atomically — the 'optimistic update' primitive: read, compute, CAS, retry on failure. That retry loop is AtomicLong.incrementAndGet on x86 (lock xadd/cmpxchg).
  • The ABA problem: CAS checks the value, not the history — A→B→A slips past. Fixes: version-tagged words (AtomicStampedReference), or designs where values never recycle (immutable nodes + GC — one quiet reason lock-free structures are easier on the JVM than in C).
  • Memory barriers: atomics alone don't order other accesses; acquire/release semantics (or full fences) do — this is the hardware floor under the JMM's happens-before and volatile (a volatile write compiles to a release store, on x86 usually plain store + no reordering thanks to TSO; ARM needs real barriers).
  • Cost intuition: uncontended CAS ≈ a few ns; contended = cache-line ownership bounces between cores at ~40–100ns per hop — why LongAdder (striped cells) beats AtomicLong under fire, and why per-core/sharded counters are an OS-kernel pattern too.

🔄 Likely follow-up questions

  • Why can't Peterson's algorithm work on modern CPUs without barriers?
  • What is LL/SC (ARM) and how does it differ from x86 CAS?
  • When is a lock-free structure actually slower than a locked one?