Atomics & Lock-Free
Atomic reads, writes and compare-and-swap, why an atomic variable does not make a multi-step invariant safe, and lock-free concepts treated honestly as progress guarantees rather than performance promises — CAS loops, the ABA problem, wait-free versus lock-free.
An atomic operation is one no other thread can observe half-done. That buys exactly one thing: a single memory location read-modify-written without a lock. It does not buy an invariant spanning two locations, and it does not buy check-then-act.
Q · Which operations does an atomic variable actually make indivisible, and which ones does it leave exposed?
CAS writes only if the location still holds the value you read. That turns an arbitrary read-modify-write into an optimistic loop: read, compute, attempt, and on failure re-read and recompute. The loop is the point — and so is the fact that it can spin.
Q · How does compare-and-swap turn a multi-step update into something safe without a lock, and what does the retry cost?
Two atomic variables give you two indivisible operations, not one. Every invariant that relates them lives in the gap between the two operations, and no amount of making each one more atomic closes that gap.
Q · Why do two individually correct atomic operations still break the invariant that spans them?
Lock-free means the system as a whole always advances: no thread can be blocked forever by another thread being descheduled, killed or slow. It says nothing about throughput, latency or simplicity, and it is routinely chosen for the wrong reason.
Q · What does calling an algorithm lock-free actually promise, and what does it deliberately not promise?
One head pointer and one CAS gives you a working push. The educational version fits on a screen and is genuinely instructive — and it is not production code, because everything it leaves out is where lock-free structures actually go wrong.
Q · How does a CAS on a single head pointer implement a whole stack operation, and what does the simplified version leave out?
Lock-free guarantees that some thread completes. Wait-free guarantees that every thread completes, in a bounded number of its own steps. The gap between "some" and "every" is where one unlucky thread starves while every dashboard says the system is healthy.
Q · If lock-free guarantees progress, why can one particular thread still make none?
Your CAS expected A, found A, and succeeded. In between, the value became B and then A again — and the world it pointed at is no longer the world you read. Value equality was never evidence that nothing happened.
Q · The CAS succeeded and the value was exactly what I expected — how can the structure still be corrupt?