What four conditions must hold for a deadlock to occur? — Cracked Java
// Concurrency & Multithreading · Deadlock, Livelock & Starvation
SeniorTheoryBig TechAmazonGoogle

What four conditions must hold for a deadlock to occur?

A deadlock requires all four Coffman conditions to hold at once: mutual exclusion, hold-and-wait, no preemption, and circular wait. Break any single one and deadlock becomes impossible.

The four conditions

  • Mutual exclusion. At least one resource is non-shareable — held exclusively by one thread. A lock is the obvious example; if every resource could be shared freely there would be nothing to wait for.
  • Hold and wait. A thread holds at least one resource while requesting another. If threads always acquired everything they need atomically (all-or-nothing), they would never sit holding A while blocked on B.
  • No preemption. Resources cannot be forcibly reclaimed; the owning thread must release them voluntarily. The JVM never yanks a monitor away from a thread, which is why intrinsic locks satisfy this condition by design.
  • Circular wait. There exists a cycle of waiting threads: T1 waits on a lock held by T2, T2 on one held by T3, ... and the last waits on one held by T1.

These are necessary together. A system can satisfy three of them indefinitely and never deadlock — it is the simultaneous presence of the fourth, usually circular wait, that closes the trap.

Mapping conditions to prevention

Each condition suggests a way to break the deadlock:

// Breaks CIRCULAR WAIT: always acquire locks in a fixed global order.
// Order by System.identityHashCode so any two threads agree on which to take first.
void transfer(Account from, Account to, long amount) {
    Account first  = System.identityHashCode(from) < System.identityHashCode(to) ? from : to;
    Account second = first == from ? to : from;
    synchronized (first) {
        synchronized (second) {
            from.debit(amount);
            to.credit(amount);
        }
    }
}
  • Break hold-and-wait with tryLock() timeouts (acquire all or back off and release).
  • Break no preemption by using interruptible/timed locks (lockInterruptibly, tryLock(timeout)).
  • Break circular wait with consistent lock ordering (shown above) — usually the cheapest and most robust.
  • Mutual exclusion is hardest to remove, but lock-free/CAS structures or immutable data sidestep it.

Mark your status