死锁
2026/8/24大约 1 分钟
死锁
死锁的产生条件与示例,以及如何避免死锁。
什么是死锁
当线程需要同时持有多个锁时可能产生死锁:
- 线程 A 持有锁 lock1,试图获取 lock2(被 B 持有)
- 线程 B 持有锁 lock2,试图获取 lock1(被 A 持有)
- 双方都在等待对方释放锁,又都不释放自己持有的锁 → 永久阻塞
死锁示例
public class Deadlock {
private String objID;
public Deadlock(String id) { objID = id; }
// 调用 other 的 action(),会试图获取 other 对象的锁
public synchronized void checkOther(Deadlock other) {
other.action();
}
public synchronized void action() { }
}两个线程交叉调用:
final Deadlock obj1 = new Deadlock("obj1");
final Deadlock obj2 = new Deadlock("obj2");
// 线程 A:持有 obj1 锁,试图获取 obj2 锁
new Thread(() -> obj1.checkOther(obj2)).start();
// 线程 B:持有 obj2 锁,试图获取 obj1 锁
new Thread(() -> obj2.checkOther(obj1)).start();死锁的产生条件(四个必要条件)
- 互斥:资源每次只能被一个线程使用
- 持有并等待:线程持有资源的同时等待其他资源
- 不可剥夺:资源不能被强制抢占,只能由持有者释放
- 循环等待:多个线程形成环形等待链
避免死锁的策略
- 按顺序加锁:所有线程按相同顺序获取锁,破坏循环等待
- 加锁超时:获取锁时设置超时,超时后释放已有锁并重试
- 尽量少持有锁:缩小同步代码块范围
- 使用 Lock 接口:
ReentrantLock.tryLock()支持尝试获取,避免无限等待