Deadlocks

lock ordering

Imagine a workshop with a rule posted on the wall: 'Always take the tools in this order — gloves first, then goggles, then the drill — and never grab a lower one while holding a higher one.' If everyone obeys, two workers can never end up each clutching one tool the other needs, because both reach for them in the same sequence. Lock ordering is exactly this discipline applied to locks in concurrent programs, and it is the single most practical defense against deadlock.

The idea is the concrete, code-level form of breaking the circular-wait condition. You assign every lock a fixed position in a global order (often just a number, or a documented hierarchy), and you make it a strict rule that any thread acquiring multiple locks must acquire them in increasing order. Because a circular wait requires some thread to hold a higher-ordered lock while requesting a lower-ordered one, and the rule forbids exactly that, no cycle of waiting can ever form. When code genuinely cannot honor the order, the fallback is to use a try-lock-and-back-off protocol: attempt the out-of-order lock without blocking, and if it fails, release everything and restart.

Honest caveats make or break this technique. The ordering must be GLOBAL and FOLLOWED EVERYWHERE — a single function, library, or callback that grabs locks in the wrong order can reintroduce deadlock. It can be hard to define a clean total order when locks are created dynamically or hidden behind abstractions, and nested locking through layered code makes the real acquisition order hard to see. Tools help: runtime lock-order checkers (such as lockdep in the Linux kernel) watch every acquisition and flag any violation of the established order before it causes a real hang.

transfer(from, to): lock the account with the smaller id first, then the larger. So transfer(A, B) and transfer(B, A) both lock min(A, B) before max(A, B), and can never each hold one lock the other needs — no circular wait, no deadlock.

A consistent global lock order makes the classic two-lock deadlock impossible.

Lock ordering works only if applied globally and consistently — one path that takes locks out of order reintroduces deadlock. Dynamic or hidden locks make a clean total order hard; runtime checkers like lockdep help catch violations.

Also called
lock hierarchylock-acquisition order鎖階層取鎖順序