缩略图是 GPT 绘制的死锁场景:进程各自占有资源并互相等待,形成一个环。中间的部分好像就是资源吧?这幅图把电路画得很有立体感,哈哈。
计算机突然卡住或毫无响应,有时可能是
死锁(deadlock)
造成的。死锁是指多个进程互相等待对方的资源,导致
彼此阻塞
的情况。
本文将逐步整理死锁产生的条件,以及解决死锁的各种方法。这也是面试中的常见理论,因此结合示例准确理解非常重要。
死锁是两个或更多进程各自占有资源,同时等待对方持有的资源,以至于永远无法继续执行的状态。
例如:P1 占有打印机,P2 占有扫描仪,随后两者分别请求并等待对方的资源,就会因互相等待而停滞。

(互相等待)到底什么时候才结束呢……?
P1 占有打印机,P2 占有扫描仪。此时 P1 等待 P2 的扫描仪,P2 则等待 P1 的打印机。这样彼此阻塞的状态,就是死锁。
以下四个条件同时成立时,会发生死锁。
互斥(Mutual Exclusion)
:一个资源同时只能由一个进程使用。
占有并等待(Hold and Wait)
:持有资源的同时等待其他资源。
不可抢占(No Preemption)
:无法强行收回资源。
循环等待(Circular Wait)
:多个进程互相请求资源,形成环形等待。
只要破坏其中任意一个条件,就不会发生死锁。因此,解决策略是设法消除至少一个条件。
通过设计,让某个 Coffman 条件
从一开始就无法成立
。
- 防止占有并等待:请求资源时一次分配全部资源;若不能预先获取所需资源,就不分配任何资源。
- 防止循环等待:为资源分配唯一编号,始终按编号顺序请求。
进程请求资源时,先确认批准请求后系统是否仍处于安全状态,再决定是否允许。典型方法是
银行家算法(Banker's Algorithm)
。
例如,银行向客户放贷时,会先计算是否可能造成整体资金不足,再决定批准与否,原理与此类似。
允许死锁发生,但定期检查系统以检测死锁。
可以使用*资源分配图(Resource Allocation Graph)
或
等待图(Wait-for Graph)*进行检测。
检测算法可能增加系统负担,使用时需要留意。
检测到死锁后,将系统恢复到正常状态。主要方法如下:
- 终止进程:强制结束处于死锁中的进程。
- 资源抢占:强制收回某些进程的资源,分配给其他进程。
线程环境中也经常发生死锁。例如,在 Java 中,两个线程各自获取不同对象的锁,再等待对方对象的锁,就可能发生死锁。
Java// Thread 1
synchronized(objA) {
synchronized(objB) {
// 작업
}
}
// Thread 2
synchronized(objB) {
synchronized(objA) {
// 작업
}
}
要解决这个问题,需要固定获取锁的顺序,或设置锁超时等。
本文结合示例,梳理了死锁的概念、产生条件,以及预防、避免、检测、恢复四种典型解决策略。
技术面试中,很多问题不只是询问定义,而是确认你是否
通过示例理解概念
,因此应练习把各个条件与策略联系到实际场景。
漫长的进程相关文章终于告一段落。下一篇将介绍计算机内存的基本部分——
主存
的结构。