什么是进程的死锁?
进程死锁(Deadlock)是指一组进程在执行过程中,彼此互相等待,导致这些进程都无法继续执行的情况。换句话说,进程因互相占有资源并且相互等待对方释放资源而陷入了永久等待的状态。
举例说明:
- 假设有两个进程 P1 和 P2,以及两个资源 R1 和 R2。
- 进程 P1 拥有资源 R1,并且请求资源 R2。
- 进程 P2 拥有资源 R2,并且请求资源 R1。
产生死锁的四个必要条件(Coffman 条件):
死锁的发生需要满足以下四个条件,如果这四个条件同时成立,就可能导致死锁:
-
互斥条件(Mutual Exclusion):
- 至少有一个资源是不能共享的,即每次只能被一个进程使用。进程对资源的独占使用是死锁的基础。
-
占有并等待(Hold and Wait):
- 一个进程已经持有了某些资源,并且还在请求其他资源,但该进程在等待请求的资源时不会释放它已经占有的资源。
-
不可剥夺(No Preemption):
- 资源不能被强行剥夺,进程只能自愿释放已占有的资源。如果一个进程已经占有某个资源,操作系统不能强制其释放。
-
循环等待(Circular Wait):
- 存在一组进程,每个进程都在等待下一个进程所占有的资源,形成一个闭环。即进程 P1 等待 P2 的资源,P2 等待 P3 的资源,最后 Pn 等待 P1 的资源。
只有当这四个条件同时满足时,死锁才可能发生。解决死锁问题的关键就在于如何打破这些条件中的一个或多个。
如何解决进程死锁?
解决死锁的方法主要分为四大类:预防死锁、避免死锁、检测和恢复死锁、以及忽略死锁。每种方法都有各自的优缺点。
1. 预防死锁(Deadlock Prevention)
通过破坏四个死锁条件中的一个或多个来预防死锁。常见的预防策略包括:
-
破坏互斥条件:
- 让资源可以被多个进程共享,避免资源的独占使用。
- 缺点:有些资源本质上就是非共享的(如打印机),所以这种方法不总是可行的。
-
破坏占有并等待条件:
- 进程在请求资源时必须一次性请求所有资源。如果无法得到所有资源,则进程不会占有任何资源,从而避免占有并等待。
- 缺点:这种方法可能会导致资源利用率低,因为进程可能会一次性请求大量资源,而这些资源可能在一段时间内不会被使用。
-
破坏不可剥夺条件:
- 如果一个进程请求某个资源而得不到,那么它必须释放已经占有的资源。之后,它可以稍后重新尝试获取资源。
- 缺点:这种策略可能会导致进程重新进行繁琐的操作,增加系统开销。
-
破坏循环等待条件:
- 通过对资源进行线性排序,要求进程按一定顺序请求资源。如果进程需要多个资源,它必须按序号递增的顺序请求资源。
- 缺点:强制进程按顺序请求资源可能导致进程无法按照最佳顺序执行。
2. 避免死锁(Deadlock Avoidance)
避免死锁的方法通常使用资源分配算法,如 银行家算法。该算法根据当前资源分配情况,判断是否会发生死锁。如果发现可能发生死锁,系统将拒绝资源请求。
- 银行家算法:
- 通过模拟资源分配的安全状态,系统在每次资源分配之前都会进行测试,确保资源分配不会导致死锁。如果资源分配后系统处于“安全状态”,则允许分配;否则拒绝请求。
- 缺点:算法复杂,计算开销较大,而且需要进程提前声明所需的最大资源数量,不适用于动态或不可预测的资源需求场景。
3. 死锁检测与恢复(Deadlock Detection and Recovery)
允许系统在运行过程中检测死锁,并采取恢复措施来解除死锁。
-
死锁检测:
- 系统通过检测进程之间的资源等待图(资源分配图)来判断是否存在死锁。如果存在一个环,则表示可能发生死锁。
-
恢复措施:
- 终止进程:终止某个或某些进程,以释放其占有的资源。
- 可以选择优先终止代价较低的进程。
- 剥夺资源:从某个进程中强制剥夺资源,将资源分配给其他等待的进程。
- 缺点:恢复措施可能会导致数据丢失或进程重新执行,影响系统的正常运行。
- 终止进程:终止某个或某些进程,以释放其占有的资源。
4. 忽略死锁(Deadlock Ignorance)
有时候,系统会选择忽略死锁问题。例如,Unix 和 Windows 大多数情况下并不检测死锁,而是采取“鸵鸟算法”(Ostrich Algorithm),即假装死锁不会发生。这是因为死锁的发生概率较低,强制解决死锁的开销可能比死锁本身带来的问题还要大。
- 优点:简单易行,系统不必耗费大量资源去监控和预防死锁。
- 缺点:一旦发生死锁,系统可能会卡死或出现不可预测的行为,需要手动干预。
总结:
进程死锁 是多个进程因为竞争资源而互相等待,导致它们无法继续执行。死锁发生的四个必要条件是:互斥、占有并等待、不可剥夺、循环等待。解决死锁可以通过预防(打破死锁条件)、避免(通过银行家算法)、检测与恢复(检测死锁后采取恢复措施)或者忽略(死锁发生概率较低时)等方法。每种方法都有其优缺点,实际应用中会根据场景选择合适的策略。