Part 3 · 1 chapters · ~8 min
Lock-Free Basics
Atomic operations and compare-and-swap, a lock-free counter and stack, the ABA problem, progress guarantees (lock-free, wait-free, obstruction-free), why lock-free is not automatically faster (contention, measured in Computers part 8), and when to use the libraries instead.
6
Compare-and-swap
code
// compare-and-swap loop: retry until no one else changed the value in between
// (Go)
for {
old := atomic.LoadInt64(&balance)
if old < amount { return ErrInsufficient }
if atomic.CompareAndSwapInt64(&balance, old, old-amount) { return nil } // succeeded atomically
// someone else changed it: loop and try again with the new value
}
// Java: AtomicLong.updateAndGet, LongAdder for heavily contended counters (stripes internally)
LongAdder requests = new LongAdder(); requests.increment(); long total = requests.sum();| concept | meaning |
|---|---|
| lock-free | some thread always makes progress, even if others are paused |
| wait-free | every thread finishes in a bounded number of steps |
| ABA problem | a value changes A → B → A between your read and your CAS, so CAS succeeds wrongly; fix with version counters or hazard pointers |
| contention | many threads CASing one location retry constantly; striping (LongAdder) or sharding helps |
Lock-free structures are hard to write correctly. Use the ones your platform provides (Java's java.util.concurrent, Go's sync/atomic and channels, Rust's crossbeam) and keep shared state small.