Deadlock — Lock Ordering Puzzle
Reorder how threads take their locks so none can wait on each other forever. A puzzle that teaches the global lock ordering rule every engineer learns the hard way.
Reorder each thread so no two can wait on each other forever.
- 🔒 A
- 🔒 B
- 🔒 B
- 🔒 A
How to play
- Each row is a thread, and the chips are the locks it takes, left to right.
- Drag a chip (or use the arrows) to change the order a thread acquires its locks.
- If two threads take the same pair in opposite orders they can freeze forever. The fix is a single global order every thread agrees on — press Run to check.
How it works
Each row is a thread and each chip is a lock it acquires, left to right. When two threads take the same pair of locks in opposite orders, an interleaving exists where both hold one and wait for the other — and neither ever moves again. Press Run and the wait-for graph is checked for a cycle; if one exists the offending locks light up red. The fix is the rule real codebases adopt: pick one global order for locks and make every thread follow it.
A teaching puzzle. It models hold-and-wait cycles, which is the deadlock condition you can design away; real systems also have to think about timeouts, lock-free structures and livelock.
Frequently asked questions
What actually causes a deadlock here?
A cycle in the wait-for graph. If thread 1 holds A and wants B while thread 2 holds B and wants A, both wait forever. The game draws exactly that cycle when it finds one.
Why does sorting the locks fix it?
If every thread acquires locks in the same global order, a cycle is impossible: a thread can only ever wait on a lock later in the order than the ones it holds, so the wait-for graph stays acyclic. That is the standard lock-hierarchy rule.
Is this how real deadlocks are found?
The cycle check is the same idea used by lock-order-inversion detectors such as ThreadSanitizer and Java lock analysers. Real tools observe orders at runtime; here you can see the whole graph at once.