06

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.

Demo 06Source on GitHub ↗

The full source for this example lives in examples/concurrency/06-lock-ordering/ — clone the repo, cd in, 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