背景
哲学家进餐问题:有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上共有五个碗和五只筷子,他们的生活方式是交替的进行思考和进餐。平常,一个哲学家进行思考,饥饿时便试图取其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐完毕,放下筷子继续思考。
如果每一个哲学家因饥饿而都拿起了他们的左边的筷子,当每一个哲学家又试图去拿起他们右边的筷子时,将会因无筷子拿而无限地等待,从而产生死锁问题。
通常见的死锁问题还有进程p1占着打印机而请求扫描仪,p2占着扫描仪而请求打印机,也会产生死锁问题。
资源问题
在系统中有不同类型的资源,其中可以引起死锁的主要是:需要采用互斥访问方法的、不可被抢占的资源,即临界资源,如打印机、数据文件、队列、信号量等。
可重用性资源
一种可供用户重复使用多次的资源
- 资源中的单元只能分配给一个进程使用,不允许多个进程共享。
- 按照 请求资源 -> 使用资源 -> 释放资源
- 系统中每一类可重用资源中的单元数目是相对固定的,进程不能创建和删除它。
可消耗性资源
又称为临时性资源,在进程的运行期间,由进程动态地创建和消耗。最典型的可消耗性资源如进程间通信的消息等。
可抢占性资源
是指某进程在获得该类资源后,该资源可以被其他的进程或者系统抢占。如cpu和主存均属于可抢占性资源,对于这类资源是不会引起死锁的。
不可抢占性资源
即一旦系统把某资源分配给该进程后,就不能将它强行收回,只能在进程用完后自行释放。如打印机、磁带机等。
死锁的产生
通常是源于多个进程对资源的争夺,不仅对不可抢占资源进行争夺时会引起死锁,而且对可消耗资源进行争夺时,也会引起死锁。
- 竞争不可抢占性资源引起死锁
- 竞争可消耗资源引起死锁
- 进程推进顺序不当引起死锁:如并发进程p1和p2随着推进进入了不安全区D
死锁的定义
如果一组进程中的每一个进程都在等待仅由该进程中的其他进程才能引发的事件,那么该组进程就是死锁的(deadlock)
产生死锁的必要条件
死锁必须同时具备下面四个必要条件,只要其中任一个条件不成立,死锁边不会发生。
- 互斥条件:在一段时间内,某资源只能被一个进程占用。
- 请求和保持条件:进程已经保持了至少一种资源,但又提出了新的资源请求,而该资源已被其他进程占用,此时阻塞,但对自己的获取的资源保持不放。
- 不可抢占条件:不能被抢占,只能自己释放
- 循环等待条件
处理死锁的方法
- 预防死锁
- 避免死锁
- 检测死锁
- 解除死锁
上述四种方式,从1到4,防范程度逐渐减弱,但对应的是资源利用率的提高,以及进程资源因素而阻塞的频率下降(即并发程度的提高)
预防死锁
预防死锁的方法是通过破坏产生死锁的四个必要条件中的一个或者多个,由于互斥条件是非共享设备必须的,不仅不能改变,而且还要保证,所以主要是破坏后三个。
破坏‘请求和保持’条件
- 第一种协议:所有进程在开始运行之前,必须一次性的申请整个过程中的所需资源。优点:简单、易行且安全;缺点:资源被严重浪费、使其他进程经常发生饥饿现象。
- 第二种协议:对第一个协议的改进,它允许一个进程只获得初期所使用的资源,便开始运行,在运行过程中,在逐步释放已分配给自己的、已经用完毕的全部资源,然后在请求新的资源。
破坏‘不可抢占’条件
- 规定:当一个已经保持了某些不可被抢占资源的进程,提出新的资源请求而不能得到满足时,它必须释放已经保持的所有资源,待以后需要时重新申请。这意味着该进程占用的资源会被暂时释放,后者说是被抢占了。
- 缺点:实现复杂,代价太大,可能会引起前后二次的信心不一致。
破坏‘循环等待’条件
- 对系统中所有的资源进行线性排序,并赋予不同的序号,规定每个进程必须按序号递增的顺序请求资源。
- 缺点:要求系统中的资源相对稳定,这就限制了新类型设备的增加;其次,作业使用各个资源的顺序和系统中的顺序不一致,造成对资源的浪费;第三,按规定次序申请资源的方法限制了用户简单自主的编程。
避免死锁
同样属于事前预防的策略,在资源动态分配的过程中,防止系统进入不安全的状态,以避免死锁。
系统安全状态
- 所谓安全状态是指系统能按某种进程推进顺序(P1,P2,P3...Pn)为每个进程Pi分配其所需资源,直至满足每个进程的最大需求,使每个进程都可以顺利地完成,此时P1,P2,P3...Pn为安全序列,如果系统无法找到这样一个安全序列,则称系统处于不安全状态,可能会进入死锁。
- 避免死锁的基本思路:确保系统始终处于安全状态,一个系统开始是处于安全状态的,当有进程请求一个可用资源时,系统需要对该请求进行计算,若将资源分配给进程后系统仍处于安全状态,才将资源分配给进程。
利用银行家算法避免死锁
死锁的检测与解除
死锁检测算法:以确定系统中是否发生了死锁
接触算法:如果发生了死锁,利用该算法解除。
死锁的检测
- 资源分配图
由一组节点N和一组边E组成的一个对偶G=(N,E),N为2个互斥的子集,P={P1,P2,P3...Pn}进程节点, R=资源节点,N= P 并 R;边e={Pi,Rj} 或者 {Rj,Pi}, 理解为一个有向图,{Pi,Rj}表示Pi请求资源Rj,{Rj,Pi}表示Rj被Pi当前保持。 - 死锁定理:判断该有向图中是否有环,如果有环代表需要互相等待进入死锁,所以检测的方法是:建拓扑序列。
死锁的解除
最简单的方式是人工干预,或者利用死锁解脱算法。
- 终止进程的方法:终止所有死锁进程;逐个终止(按照某种顺序)。
- 付出代价最小的死锁解除算法