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 lockBStep-by-Step Fix
- 1
Identify the deadlock
Take a thread dump with jstack or kill -3. Look for 'Found Java-level deadlock' in the output.
- 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
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