NOTE

6.37 Deadlock Example

A minimal Java deadlock caused by inconsistent lock ordering, plus detection and prevention techniques.

JavaCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. Minimal Example

Two threads can deadlock when each holds one lock and waits for the other:

static final Object LOCK1 = new Object();
static final Object LOCK2 = new Object();

Thread a = new Thread(() -> {
    synchronized (LOCK1) {
        synchronized (LOCK2) {
            // work
        }
    }
});

Thread b = new Thread(() -> {
    synchronized (LOCK2) {
        synchronized (LOCK1) {
            // work
        }
    }
});

If a owns LOCK1 while b owns LOCK2, both can wait forever for the other monitor.

2. Why It Happens

The classic Coffman conditions are mutual exclusion, hold-and-wait, no forced preemption, and circular wait. Removing at least one necessary condition prevents this form of deadlock.

3. Diagnose It

A Java thread dump can show threads waiting for monitors and often reports a detected Java-level deadlock. Useful tools include jstack, jcmd Thread.print, and observability tooling that captures thread dumps.

4. Prevent It

The simplest rule for multiple locks is a global lock ordering: all code acquires the same locks in the same order.

Other approaches include reducing nested locking, using higher-level concurrent structures, or using timed tryLock with a deliberate retry/rollback policy when Lock is appropriate.

Loading helpful count