一种记录进程共享资源的历史和分析死锁的工具。两个进程的联合进程图是一个二维网格
联合进程图中的死锁区域也称为敏感区域。
如上图,两个进程的联合进程图,展示了六条不同的路径(A、B是两个不同的资源):
Q进程获得B,然后获得A,再释放B和A;当P进程恢复执行时,它可以获得全部的资源;Q进程获得B,然后获得A;P进程开始执行但阻塞在对A的请求上;Q进程释放B和A;当P进程恢复执行时它可以获得全部资源;Q进程获得B,然后P进程获得A;Q继续执行但阻塞在对A的请求上;P进行继续执行但阻塞在对B的请求上,构成死锁;P进程获得A,然后Q进程获得B;Q继续执行但阻塞在对A的请求上;P进程继续执行但阻塞在对B的请求上,构成死锁;P进程获得A,然后获得B;Q进程开始执行但阻塞在对B的请求上;P释放A和B;当Q进程恢复执行时可获得全部资源;P进程获得A,然后获得B,再释放A和B;当Q进程恢复执行时可以获得全部资源。资源通常分为两类:可重用资源和可消耗资源。
可重用资源是指一次只能供一个进程安全使用,且不会由于使用而耗尽的资源。包括处理器、I/O通道、内存和外存、数据库和信号量之类的数据结构,等等。可消耗资源是指可以被创建和销毁的资源,通常对某种类型可消耗资源的数目没有限制。例如中断、I/O缓冲区中的信息。处于等待/阻塞状态的进程无法自己改变自己的状态,需要其他进程来改变。
死锁的三个必要条件:
第四个条件,实际上是前三个条件的潜在结果:
只有三个必要条件都满足,才可能出现死锁
方法:允许多个进程同时使用资源;
使用条件:资源的固有特性允许多个进程同时使用或借助特殊的技术允许多个进程同时使用(如打印机借助spooling技术)
缺点:不适用于绝大多数资源;
方法:禁止已拥有资源的进程再申请其他资源,如要求所有进程在开始执行前一次性地申请在整个运行过程中所需要的全部资源;或申请资源时先释放其占有的资源后再一次性申请所需的全部资源。
优点:简单容易实现、安全;
缺点:进程延迟运行,资源浪费严重;
方法:
一个已占有某些资源的进程在申请其他新资源但无法立即得到满足时必须释放它占有的所有资源待以后需要再重新申请;操作系统可以剥夺一个进程占有的资源并分配给其他进程;适用条件:资源的状态可以容易地保存和恢复。
缺点:实现复杂、代价大、需要反复申请/释放资源、系统开销大。
方法:对所有资源按照类型进行线性排队,进程申请资源必须严格按照资源序号递增的顺序。
缺点:虽然可以避免循环等待但是容易造成资源的浪费,且会使得进程的执行速度变慢。
不需要事先采取限制措施破坏产生死锁的必要条件,而是在资源的动态分配过程中采用某种策略,防止系统进入不安全状态,从而避免发生死锁。
两种方案:
如果一个进程的请求会导致死锁,则不启动此进程;如果一个进程增加的资源请求会导致死锁,则不允许分配;模型:
N个进程,M种资源;系统资源总量向量R=(R1,R2, … , Rm),Rj为第j种资源的总数;系统当前可用资源总量向量V=(V1,V2, … , Vm),Vj为第j种资源的剩余数量;进程-资源需求(Claim)矩阵C,Cij表示进程i对资源j的请求数;进程-资源分配(Allocation)矩阵A,Aij表示当前已经分配给进程i的资源j数;系统正常状态下模型有如下性质:
Rj=Vj +(A1j+A2j+…+Anj),对所有的j=1,2,…,m(总资源数=可用资源数+已分配资源数);Cij ≤ Rj ,对所有的i=1,2,…,n, j=1,2,…,m(要申请的资源数不能超过资源总数);Aij ≤ Cij ,对所有的i=1,2,…,n, j=1,2,…,m(已分配的资源数不能超过对这个资源的请求数);进程启动拒绝的策略:若Rj≥Cn+1, j +(C1j+C2j+…+Cnj), j=1,2,…,m,则允许启动进程Pn+1,否则系统不启动进程Pn+1;(有足够的资源被进程Pn+1请求)。本策略不能保证资源的最优使用率,但可以保证系统现有进程不会发生死锁。
模型:
系统状态由资源总量向量R=(R1,R2, … , Rm )、系统可用资源总量向量V=(V1,V2, … , Vm )、进程-资源需求矩阵C和进程-资源分配矩阵A表示;安全状态:至少存在一个执行时序(资源分配序列)使得当前所有进程都能运行到结束状态;不安全状态:不存在一个执行时序可以使得当前所有进程都能运行到结束状态;只要系统处于安全状态,就必定不会发生死锁;而不安全状态不一定是死锁状态,但不能保证不会进入死锁。
避免策略:
如果一个新进程的资源请求会导致不安全状态,则拒绝启动这个进程;如果满足一个进程新提出的资源请求后会导致不安全状态,则拒绝分配资源给这个进程;算法:
全局数据结构:
资源分配算法:
要求该进程已分配的资源数和当前请求的资源数的综合不可超过进程申请的资源总量;如果进程当前请求的资源数超过该资源的可用数量则挂起进程;否则分配资源给进程(但如果判断出分配后系统不存在安全状态则会恢复到未分配时的状态);测试安全算法(银行家算法):
在进程集合中找到一个进程可以满足进程申请的所有资源数减去已经分配的资源数小于当前可用的资源数。如果满足的话则说明可以将该进程还需要的资源都分配给该资源并让其可以执行完成然后释放其占有的所有资源以供其他进程使用。如果不满足则恢复原始状态,不分配资源给该进程。优点:
比死锁预防的限制少;无需死锁预防中的资源剥夺和进程重启;缺点:
必须事先声明每个进程请求的最大资源;考虑的进程必须是无关的,即它们的执行顺序没有任何同步要求的限制;分配的资源数目必须是固定的;在占有资源时进程不能退出;检测的时机:资源申请时;周期性检测。
检测方法:
单个资源实例:检测资源分配图中是否存在环路;多个资源实例:类似银行家算法的安全检查;恢复:
连续剥夺资源直到不再存在死锁;(剥夺法)把每个死锁进程回滚到前面定义的某些检查点,并且重新启动所有进程(回退法)杀死所有死锁进程,或连续杀死死锁进程直到不再存在死锁;(杀死进程法)死锁避免、检测和预防之间的区别:预防是通过限制三种死锁的必要条件的至少一个或者直接限制循环等待的发生;避免允许可能出现的必要条件发生,但是采取措施防止系统进入不安全状态,确保不会出现死锁;检测是允许资源的自由分配,采取周期性的措施来发现并处理可能存在的死锁情况。
死锁与饥饿的经典问题——5个哲学家思考+吃意大利面,每人必须用两把叉子吃,但总共只有5把叉子,要求避免死锁和饥饿,
解决方案:每次只允许四个人进餐。这是采用了死锁预防——防止循环等待出现的方案。