Chapter 06 — AB/BA Deadlock and the scoped_lock Fix
Two threads that acquire the same two mutexes in opposite order deadlock with lock_guard, and cannot with scoped_lock.
The full source for this example lives in
examples/concurrency/06-lock-ordering/— clone the repo,cdin, and./demo.sh.
Chapter reference: Doc 06 — Mutual Exclusion and Locking
What it shows
Two mutexes and two threads acquire them in opposite order under std::lock_guard, with a std::latch closing the scheduling window so the circular wait happens on every run instead of depending on luck — that mode never exits on its own, and the non-exit is the point. The same opposing-order acquisition repeated under std::scoped_lock always completes, because scoped_lock’s deadlock-avoidance algorithm is indifferent to argument order. The verifier runs the deadlock build under a timeout --signal=KILL and asserts it had to be killed, then runs the fixed build and asserts it always finishes with the correct operation count — both hard assertions, since a latch-forced deadlock has no scheduling noise to make soft.
Running it
cd examples/concurrency/06-lock-ordering
./demo.sh # build + run lock_ordering (both modes) + verify.lua
./demo.sh --clean # remove the image