主题
概念卡片:死锁
一句话机制:死锁 = 多个进程因循环等待对方持有的资源而永久阻塞。它必须四个必要条件同时成立才会发生;预防(破坏条件)/避免(银行家算法)都是围绕这四条件做文章。
四大必要条件
| 条件 | 含义 | 能否破坏 |
|---|---|---|
| 互斥 | 资源只能被一个进程独占 | ❌ 不能破坏(锁的本质) |
| 请求与保持 | 持有资源的同时再申请其他资源 | ✅ 一次性申请所有资源 |
| 不可剥夺 | 已获资源不能被强制夺走 | ✅ 申请不到就主动释放已有资源 |
| 循环等待 | 进程间形成资源申请环 | ✅ 按序申请资源(反序释放) |
预防死锁(破坏四条件)
| 破坏 | 手段 |
|---|---|
| 请求与保持 | 一次性申请所有资源 |
| 不可剥夺 | 申请不到时主动释放已占资源 |
| 循环等待 | 按顺序申请、反序释放(最常用) |
避免死锁 vs 预防死锁
- 预防:静态破坏条件,简单但资源利用率低。
- 避免:动态判断(如银行家算法),在分配前检查是否安全,避免进入不安全状态。
关键代码示例(破坏循环等待)
线程 1、2 都按「先 resource1 再 resource2」的顺序加锁,消除循环等待:
java
// 线程 1
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "线程 1").start();
// 线程 2:同样先 resource1 再 resource2(与线程 1 顺序一致)若线程 2 先抢 resource2 再抢 resource1,就会与线程 1 形成循环等待 → 死锁。
不变量(必须成立的约束)
- 死锁发生必须四条件同时满足,缺一不可。
- 互斥条件无法破坏(临界资源必须互斥)。
- 破坏循环等待是最常用的预防手段。
常见误解
- 以为「死锁只能靠预防」→ 还有避免(银行家算法)和检测/恢复。
- 以为「破坏互斥条件也能预防死锁」→ 互斥是锁的固有属性,无法破坏。
- 把死锁与「资源不足」混淆 → 资源不足导致阻塞但未必死锁,死锁是循环等待。
关联
- 同步机制:概念卡片:进程间通信与线程同步
- 进程线程:概念卡片:进程与线程
- 总览:操作系统技术栈总览