Thread Deadlock

Found one Java-level deadlock: Thread-1 waiting on lock held by Thread-2, Thread-2 waiting on lock held by Thread-1

Quick Answer

Two or more threads are each waiting for a lock held by the other. Always acquire locks in a consistent order.

Why This Happens

Deadlock occurs when thread A holds lock 1 and waits for lock 2, while thread B holds lock 2 and waits for lock 1. Neither thread can proceed. This is a classic concurrency bug that is hard to detect because it depends on timing.

The Problem

// Thread 1: synchronized(lockA) { synchronized(lockB) { ... } }
// Thread 2: synchronized(lockB) { synchronized(lockA) { ... } }
Object lockA = new Object(), lockB = new Object();
new Thread(() -> { synchronized(lockA) { synchronized(lockB) {} } }).start();
new Thread(() -> { synchronized(lockB) { synchronized(lockA) {} } }).start();

The Fix

// Always acquire locks in the same order
Object lockA = new Object(), lockB = new Object();
new Thread(() -> { synchronized(lockA) { synchronized(lockB) {} } }).start();
new Thread(() -> { synchronized(lockA) { synchronized(lockB) {} } }).start();
// Both threads acquire lockA first, then lockB

Step-by-Step Fix

  1. 1

    Identify the deadlock

    Take a thread dump with jstack or kill -3. Look for 'Found Java-level deadlock' in the output.

  2. 2

    Find the lock ordering violation

    Examine which locks each thread holds and which it is waiting for. Find where the ordering is inconsistent.

  3. 3

    Fix lock ordering

    Ensure all threads acquire locks in the same global order. Consider using java.util.concurrent.locks with tryLock() for timeout-based deadlock avoidance.

Bugsly catches this automatically

Bugsly's AI analyzes this error pattern in real-time, explains what went wrong in plain English, and suggests the exact fix — before your users even report it.

Try Bugsly free