liveBook · Manning

Deadlock

As explained in Troubleshooting Java, Second Edition

A deadlock is a concurrency failure in which threads or transactions wait indefinitely for locks or resources held by one another.

A deadlock occurs when two or more threads wait indefinitely for locks or resources held by one another. The application usually freezes because no blocked thread can continue. section 8.0 section 8.3

Deadlocks commonly arise when synchronized code acquires multiple monitors in inconsistent orders. One thread can hold listA while waiting for listB, while another holds listB while waiting for listA. section 8.1

Investigate a frozen Java application with a thread dump:

  • Reproduce or observe the freeze, then capture a snapshot of all JVM thread states with VisualVM, another profiler, or a JDK command-line tool. section 8.1.1 section 8.3
  • Discard threads that are not blocked and inspect each blocked thread’s state, stack trace, held locks, and lock it is waiting to acquire. section 8.2.1
  • Follow lock IDs from a waiting thread to the thread holding that lock. If the chain returns to an already inspected thread, the cycle identifies the deadlock. section 8.2.1
  • Use instrumentation or lock profiling when a snapshot is insufficient and execution dynamics, contention, or lock duration must be investigated. section 7.4 section 8.3

Reversed monitor acquisition

A Consumer thread enters synchronized(listA) and then waits for listB. A Producer thread enters synchronized(listB) and then waits for listA. Both remain BLOCKED, producing a simple two-thread deadlock. section 8.1 section 8.2.1

Listing 8.1 Using nested synchronized blocks for the "_Consumer" thread
public class Consumer extends Thread {

  // Omitted code

  @Override
  public void run() {
    while (true) {
      synchronized (Main.listA) {    #1

        synchronized (Main.listB) {   #2
          work();
        }
      }
    }  
  }

  // Omitted code
}

Compare the Consumer and Producer synchronized blocks to see how reversing the outer and inner monitors creates the waiting cycle. section 8.1

How Troubleshooting Java, Second Edition covers it

How deep it goes
Explains monitor-order failures and thread-dump cycle tracing, but defers execution dynamics to profiling.
Examples
Uses Consumer and Producer threads, two shared lists, reversed monitor order, and reciprocal BLOCKED thread-dump entries.
What you can do after
Diagnose deadlocks with VisualVM or JDK command-line thread dumps by tracing blocked threads, lock IDs, owners, and cycles.
How it connects
Connects deadlock with concurrency, locks, synchronized blocks, thread dumps, profiling, semaphores, latches, and barriers.

Also explained in

Compare how 15 books explain deadlock →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Troubleshooting Java, Second Edition. The section links point to the parts of the book it draws on.