Mutual Exclusion Without Hardware Support

Symptom Two threads increment a shared counter a million times each. The final value is 1,374,522. You know why: the increment is a read, an add, and a write, and the interleavings lose updates. The fix is a lock. But a lock is provided by your runtime, which gets it from the OS, which gets it from a hardware instruction — lock xchg, cmpxchg, ldrex/strex. ...

Work Stealing and Fair Scheduling

Symptom You parallelize a recursive algorithm. Quicksort, or a tree traversal, or a divide-and-conquer numeric kernel. You have 16 cores and a central task queue, and you measure a speedup of 3. ...

Model Checking, LTL, and Buchi Automata

Symptom Your distributed lock service deadlocks once a month. You cannot reproduce it. The logs show three nodes in states that, as far as you can reconstruct, should not co-occur. You add tracing. It does not happen again for six weeks, then happens twice in a day during a deploy. You write a stress test that runs a million random interleavings overnight and finds nothing. ...

The Coffman Conditions

Symptom Production is wedged. Not slow — wedged. CPU is at zero, no errors are being logged, and two threads are sitting in a lock wait with no timeout. The stack traces show thread A holding the account lock and waiting for the ledger lock, thread B holding the ledger lock and waiting for the account lock. Somebody restarts the service and it goes away. ...

Amdahl's Law

Symptom The profile was unambiguous: 94% of wall-clock time in one loop, and the loop’s iterations are independent. You parallelise it across sixteen cores, the flame graph flattens exactly as predicted, and the end-to-end time goes from 40 seconds to 17. ...