Anatomy of Deadlock
A deadlock occurs when all four Coffman conditions hold simultaneously: (1) Mutual Exclusion — a resource can only be held by one thread at a time; (2) Lock & Wait — a thread holds at least one resource and waits to acquire more; (3) No Preemption — a held resource cannot be forcibly taken from a thread; (4) Circular Wait — thread A waits for a resource held by thread B, which waits for a resource held by thread A. Remove any single condition and deadlock becomes structurally impossible.
Breaking Strategies
Attack one condition: (1) Break Mutual Exclusion — use lock-free data structures where sharing is safe. (2) Break Lock & Wait — require threads to request all resources at once (all-or-nothing). (3) Break No Preemption — implement timeout-based lock acquisition; release everything and retry on timeout. (4) Break Circular Wait — impose a global total ordering on all resources and always acquire them in that order (always lock mutex A before mutex B). Lock ordering is the simplest and most common strategy in practice.
Code Challenge
Fix the deadlock by imposing a consistent global lock ordering.
Key takeaway
A deadlock needs all four Coffman conditions. Imposing a consistent global lock ordering costs almost nothing and breaks Circular Wait — making deadlock structurally impossible.