Deadlock

Read the explanation
What if

T1 holds A and wants B. T2 holds B and wants A. Each waits for the other, forever.

Predict first

T1 takes A then B. T2 takes B then A. What happens?

012345678lock Apause()BLOCKED: wants Block Bpause()BLOCKED: wants A

Tap any block to see what that thread is doing.

  • Holding lock
  • Blocked
Step 1/4

T1 takes lock A. At the same time, T2 takes lock B.

1static final Object A = new Object();2static final Object B = new Object();3 4static void lockAThenB() {5    synchronized (A) {6        pause(); // meanwhile T2 takes B7        synchronized (B) { // BLOCKED: T2 holds B8            System.out.println("T1 done");9        }10    }11}12 13static void lockBThenA() {14    synchronized (B) {15        pause();16        synchronized (A) { // BLOCKED: T1 holds A17            System.out.println("T2 done");18        }19    }20}21 22new Thread(Main::lockAThenB, "T1").start();23new Thread(Main::lockBThenA, "T2").start(); // both wait forever

Explanation

What just happened

T1 took lock A, T2 took lock B. Then each needed the other’s lock. T1 waited for T2 to release B, and T2 waited for T1 to release A. Neither could move, so both stayed BLOCKED forever: no exception, no CPU use, just a program that stops.

Try the what-if switch

same lock order: both threads take A first. Whoever loses the race for A waits holding nothing, so it can’t block anyone. T1 finished, released both locks, and T2 went next.

The four conditions

A deadlock needs all of these at once:

  1. Locks are exclusive.
  2. A thread holds one lock while waiting for another.
  3. Locks can’t be taken away.
  4. There’s a cycle: T1 waits for T2, which waits for T1.

Break any one and deadlock is impossible. A global lock order breaks the cycle, and it’s the usual fix.

Other fixes

Finding one

Take a thread dump with jstack <pid> or your IDE. The JVM detects monitor deadlocks and prints “Found one Java-level deadlock” with both threads and the locks they hold. Paste the dump into the thread dump reader to see it in plain words.

Common questions

What causes a deadlock in Java?

Two threads take the same locks in opposite orders. Each holds one lock and waits for the other's, so both stay BLOCKED forever, with no exception and no CPU use.

How do you prevent a deadlock?

Take locks in the same global order everywhere. A thread that loses the race for the first lock waits holding nothing, so it can't block anyone. ReentrantLock.tryLock(timeout) is another way out: give up and retry.

How do I find a deadlock?

Take a thread dump with jstack <pid> or your IDE. The JVM reports "Found one Java-level deadlock" with both threads and the locks they hold. It finds the deadlock but won't break it.

Verified: this timeline matches a real program, checked in CI on JDK 21 and 25. How we verify. Unclear or wrong? Tell us