Question

What is a deadlock, and how do you avoid one?

Vault Verified
Curated Intelligence
Definitive Source
Answer

A deadlock is a state in which two or more processes are each waiting for a resource held by another, so none can proceed and none will ever proceed without intervention.

The classic shape. Thread A holds lock 1 and wants lock 2. Thread B holds lock 2 and wants lock 1. Neither will release what it holds until it gets what it wants. They wait permanently.

The four Coffman conditions, which must all hold for deadlock to be possible — and this is the useful part, because breaking any one of them prevents it:

Mutual exclusion — at least one resource is held exclusively.

Hold and wait — a process holding a resource requests another.

No preemption — resources cannot be forcibly taken back.

Circular wait — a closed chain of processes each waiting on the next.

Prevention strategies, in rough order of practicality:

Lock ordering. Establish a global order for acquiring locks and always acquire in that order. This breaks circular wait and is by far the most widely used technique, because it requires no runtime machinery — only discipline and documentation.

Lock timeouts. Attempt acquisition with a deadline, and back off and retry on failure. Breaks hold-and-wait. Introduces the possibility of livelock, where processes repeatedly retry in lockstep and still make no progress — random backoff addresses that.

Acquire everything at once, or nothing.

Reduce lock scope and duration, and prefer lock-free structures or message passing where the problem allows. The most reliable way to avoid deadlock is to hold fewer locks.

Detection and recovery — periodically check for cycles in the wait-for graph and abort a participant. Databases do this routinely, which is why applications must be prepared to retry a transaction aborted as a deadlock victim.

Where they actually appear in practice: database transactions updating rows in different orders, nested synchronised methods, mixing synchronous and asynchronous code, and connection pool exhaustion — where a task holds a connection while waiting for another connection from the same pool.

Related Questions