- 仍以生产者-消费者为例来讲述死锁问题:如果把生产者进程的
P(empty)
和P(mutex)
对调、消费者进程的P(full)
和P(mutex)
对调,就会产生死锁问题。
L19 死锁处理
死锁概念的引出
仍以生产者-消费者为例来讲述死锁问题:如果把生产者进程的
P(empty)
和P(mutex)
对调、消费者进程的P(full)
和P(mutex)
对调,就会产生死锁问题。考虑以下一种情况:
- 假设初始时缓冲区满,首先生产者进程执行,mutex 从 1 变为 0,empty 从 0 变为 -1,于是该生产者进程进入
empty等待队列
等待被唤醒; - 然后消费者进程执行,mutex 从 0 变为 -1,于是该消费者进程进入
mutex等待队列
等待被唤醒; - 如果想要唤醒生产者进程,则需要
V(empty)
,但V(empty)
的执行需要消费者进程向下执行;反之,如果想要唤醒消费者进程,则需要V(mutex)
,但V(mutex)
的执行需要生产者进程向下执行,于是遇到了死锁问题。
我们将这种多个进程由于互相等待对方持有的资源而造成的谁都无法执行的情况叫死锁。
- 假设初始时缓冲区满,首先生产者进程执行,mutex 从 1 变为 0,empty 从 0 变为 -1,于是该生产者进程进入
死锁的成因
形成死锁的原因:
- 资源互斥使用(注意与前面信号量互斥的区别);
- 进程占有一些资源又不释放,还要去申请其他资源;
- 多个进程各自占有的资源和互相申请的资源形成了环路等待。
形成死锁的四个必要条件:
- 互斥使用:资源互斥使用;
- 不可抢占:进程只能等别的进程释放资源后,才能请求使用被释放的资源;
- 请求和保持:进程一边占有了资源,一边还要去申请别的资源;
- 循环等待:多个进程各自占有的资源和互相申请的资源形成了环路等待。
★死锁的处理方法
死锁预防
破坏死锁出现的必要条件。
缺点:造成了资源的浪费。
死锁避免
检测每个资源请求,如果造成死锁就拒绝。
判断会不会造成死锁,可以通过判断能不能顺利执行来判断,如果存在一个可完成的执行序列,那当然就不会造成死锁。
银行家算法:每次在进程申请资源时,都调用银行家算法,来看是否有可完成的执行序列,如果有,则接收申请,反之意味着会造成死锁,就拒绝进程的请求。
缺点:时间复杂度大,造成时间的浪费。
死锁检测+恢复
检测到死锁出现时,让一些进程回滚,让出资源。
缺点:恢复困难,进程造成的改变很难恢复。
死锁忽略
- 就好像没有死锁一样,对于客户机,可以直接重启来解决出现的死锁问题(事实上客户机上的 Windows 和 Linux 操作系统就没有死锁相关的东西,可以通过直接重启来处理客户机上的死锁问题)。