Deadlock xảy ra khi nhiều thread chờ lock của nhau theo vòng tròn — tất cả block vĩnh viễn.
App không crash, không exception, chỉ "đứng hình".
// Thread 1: synchronized (lockA) { synchronized (lockB) {} }
// Thread 2: synchronized (lockB) { synchronized (lockA) {} }
// → cả 2 chờ lock của nhau4 điều kiện Coffman (phải đủ cả 4): mutual exclusion, hold-and-wait, no preemption, circular wait. Phá circular wait là cách thực tế nhất.
Phòng tránh:
1. Lock ordering — cùng thứ tự (mạnh nhất):
void transfer(Account from, Account to, BigDecimal amount) {
Account first = from.id() < to.id() ? from : to;
Account second = from.id() < to.id() ? to : from;
synchronized (first) { synchronized (second) { /* ... */ } }
}2. tryLock(timeout) — không block vĩnh viễn.
3. Tránh nested lock — critical section nhỏ.
4. Cấu trúc cấp cao: ConcurrentHashMap, BlockingQueue, ExecutorService thay vì sync thủ công.
5. Immutable object — không cần lock ghi.
Phát hiện: jstack <pid> hoặc kill -3 <pid> — JVM tự in "Java-level deadlock detected". ThreadMXBean.findDeadlockedThreads() programmatic.
Liên quan: livelock (thread retry vô tận, không block), starvation (thread bị chiếm tài nguyên).
Deadlock không "fix" được sau khi xảy ra — chỉ tránh bằng thiết kế: lock ít, theo thứ tự nhất quán, có timeout, ưu tiên utility cấp cao.
Deadlock occurs when multiple threads wait for each other's locks in a circular way — all blocked forever.
The app does not crash; it just "freezes".
// Thread 1: synchronized (lockA) { synchronized (lockB) {} }
// Thread 2: synchronized (lockB) { synchronized (lockA) {} }
// → both wait for each otherFour Coffman conditions (all must hold): mutual exclusion, hold-and-wait, no preemption, circular wait. Breaking circular wait is the most practical fix.
Prevention:
1. Lock ordering — same order everywhere (most effective):
void transfer(Account from, Account to, BigDecimal amount) {
Account first = from.id() < to.id() ? from : to;
Account second = from.id() < to.id() ? to : from;
synchronized (first) { synchronized (second) { /* ... */ } }
}2. tryLock(timeout) — no infinite blocking.
3. Avoid nested locks — small critical sections.
4. High-level constructs: ConcurrentHashMap, BlockingQueue, ExecutorService instead of manual sync.
5. Immutable objects — no write locks needed.
Detection: jstack <pid> or kill -3 <pid> — the JVM prints "Java-level deadlock detected". ThreadMXBean.findDeadlockedThreads() works programmatically.
Related: livelock (threads retry forever, not blocked), starvation (a thread is denied resources).
Deadlock cannot be "fixed" after the fact — avoid by design: minimal locks, consistent ordering, timeouts, prefer high-level utilities.