在多道程序环境中,多个进程可以竞争有限数量的资源。当进程申请资源时,如果没有可用资源,那么这个进程进入等待状态。有时,如果所申请的资源被其它等待进程占有,那么该进程可能再也无法改变状态。这种情况称为死锁。
资源分为多种类型,每种类型有一定数量的实例。
正常操作模式下,进程只按如下顺序使用资源:
当一组进程中的每个进程都在等待一个事件的发生,而这一事件只能由这一组进程的另一进程引起,那么这组进程就处于死锁状态
1.必要条件
如果在一个系统如下四个条件同时成立,就会引起死锁:
2.资源分配图
通过系统资源分配图的有向图可以更精确的描述死锁。
资源分配图由一个节点集合V和一个边集合E组成。
1.节点集合V分为进程集合P和资源集合R
2 边集合E
上图一个成环是死锁,一个成环不是死锁
根据资源分配图的定义,可以证明:
一般来说,处理死锁问题有三种方法:
预防或避免(prevention or avoidance)
发生死锁,检测并恢复。确定死锁是否确实发⽣, 并提供算法从死锁中恢复
忽视死锁问题,认为死锁不会发生
发生死锁有4个必要条件,所以只要确保至少一个必要条件不成立,就能预防死锁发生
1.互斥
通常不能通过否定互斥条件来预防死锁
可共享的资源不要求互斥访问,如只读⽂件;但不可共享的资源本身就是非共享的,必须要确保互斥,如打印机,一个互斥锁
2.占用并等待
为否定这一条件,应保证:当一个进程请求一个资源时,它不能占有其他资源。
实现的方法如下:
注意:让互斥和占⽤并等待不成⽴、两种⽅法的缺点是资源利⽤率低和可能发⽣饥饿问题
3.非抢占
为了确保这一条件不成立,可以是使用如下协议:
如果一个进程占有资源并申请另一个不能分配的资源(也就是说,这个进程应该等待),那么其现已分配的资源可被抢占。
如果一个进程申请一些资源,那么首先检查它们是否可用。
4.循环等待
确保其不成立地一个方法:对所有资源类型进行完全排序,且要求每个进程按递增顺序来申请资源。
假设资源类型集合R={R1,R2…Rn},为每个资源类型分配一个唯一的整数,形式地,定义一个函数F:R → N(N为自然数集合)
可采用如下协议预防死锁:
每个进程只能按递增顺序来申请资源,即一个进程开始可以申请任何数量的资源类型Ri的实例,之后,仅当F(Rj)>F(Ri)时,进程才能申请资源类型Rj的实例
采用上述死锁预防中的的方法来预防死锁有副作用:设备使用率低和系统吞吐率低。
避免死锁的另一种方法,需要额外信息,即如何申请资源。在获悉每个进程的请求和释放的完整顺序后,系统可以决定,在每次请求时是否应该等待以避免未来可能的死锁。
需要掌握的额外信息包括:
针对每次申请,系统在做决定时考虑现有可用资源、现已分配给每个进程的资源、每个进程将来申请和释放的资源来申请与释放资源
鉴于这些先验信息,可构造算法确保系统不会进入死锁状态。避免死锁是动态的方法,它根据进程申请资源的附加信息决定是否申请资源
1.安全状态
如果系统按一定顺序(存在一个顺序)为每个进程分配资源(不超过它的最大需求),且能避免死锁,那么系统状态就是安全的,如果没有,系统状态就是非安全的
避免死锁指的是确保系统不进入不安全状态
2.资源分配图法
适用于每个资源具有单个实例。
由上一节的资源分配图的变形可以避免死锁
除原来的申请边和分配边,引入了新的类型边叫需求边。需求边用虚线Pi - - > Rj,表示进程Pi可能在将来某个时刻申请资源Rj;当进程Pi申请资源Rj时,需求边变成申请边(虚线变成实线);当进程Pi释放资源Rj时,分配变成需求边
算法规则:只有在将申请边变成分配边而不会导致资源分配图形成环时,才允许申请资源。
假设进程Pi申请资源Rj,对资源的申请,把申请边变成分配边后,如果没有环就允许申请,如有环就不允许申请
下图中如果将R2分配给P2,就会创建一个环,表示系统处于非安全状态。
3.银行家算法
适用于每个资源具有多个实例
当一个新进程进入系统时,它应声明可能需要的每种类型资源实例的最大数量,当然这不能超过系统资源总和。当用户申请一组资源时,系统应确定这些资源的分配是否会使系统处于安全状态,如果会,就可以分配;否则进程应等待,直到某个进程释放了做够多的资源为止。
为实现这一算法,引入一些数据结构,这些数据结构都资源分配系统的状态进行了记录
安全性算法:确定计算机系统是否处于安全状态的算法。
STEP 1:
Work 和Finish 分别为长度m 和n的向量, 分别初始化为:
Work = Available //可分配的资源数
Finish [ i ] = false for i = 0, 1, …, n- 1
STEP 2:
查找i使其满足:Finish [ i ] = false && Need i <= Work
如果没有满足以上条件的i, 那么就跳转到STEP 4
STEP 3:
Work = Work + Allocation i
Finish[ i ] = true
返回到STEP 2
STEP 4:
如果对所有i, Finish[i] == true 那么系统处于安全状态,如果不是就处于不安全状态
资源请求算法:判断是否可安全允许请求的算法。
每次进程请求资源的时候,运行资源请求检测算法,确认是否允许请求
设Request i 为进程P i 的请求向量,当进程Pi作出资源请求时,采取如下操作:
STEP 1:
如果Requesti <= Need i , 那么转到STEP 2. 否则,产生出错条件,这是因为进程Pi 已超过了其最大请求
STEP 2:
如果Requesti <= Available, 那么转到STEP 3. 否则Pi必须等待,这是因为没有可用资源
STEP 3:
假定系统可以分配给进程Pi所请求的资源,则修改资源分配状态,进入安全性检查
4.银行家算法实例
假设一个系统,有5个进程:P0、P1、P2、P3、P4。3 种资源类型: A (10个实例), B (5个实例),C (7个实例)。
假定在时间T0,系统资源分配状态如下:
执行算法过程:
查找满足如下条件的i :Finish [ i ] = false && Needi <= Work
发现P1满足以上条件,则Finish[1] 设置为1,
Work = Work + Allocationi;
Work = 【3,3,2】+ 【2,0,0】
继续往下查找,
发现P3 满足条件,则Finish[3]设置为1,
Work = 【5,3,2】+ 【2,1,1】= 【7,4,3】;
继续往下查找,
发现P4 满足条件,则Finish[4]设置为1,
Work = 【7,4,3】+ 【0,0,2】= 【7,4,5】;
继续往下查找,
发现P0满足条件,则Finish[0]设置为1,
Work = 【7,4,5】+ 【0,1,0】= 【7,5,5】;
继续往下查找,
发现P2满足条件,则Finish[2]设置为1,
Work = 【7,5,5】+ 【3,0,2】= 【10,5,7】;
此时Finish都为true,说明分配资源后,系统仍出于安全状态,安全顺序为【P1,P3,P4,P0,P2】
对上述例子及银行家算法和安全状态的理解:
银行家算法算的是是否可以分配给某个进程某些资源,所以假设系统把资源分配后,去判断系统是否仍处于安全状态。上面例子T0时刻的资源状态,其实就是某个进程请求了某些资源后的一个状态,算法需要去判断这个状态是否安全,如果安全便可以分配。
上文提到了什么是安全状态,即在当前资源分配下,存在一个序列使所有进程运行不死锁。关键在于如何知道存在,银行家算法模拟了最坏情况,即进程每次都请求最大数量的Need(显然实际环境中进程可能只请求一个实例),如果这样分配资源仍然能使所有进程都完成,那显然这个序列就是存在的,系统就是安全的
如果一个系统既不采用死锁预防算法也不采用死锁避免算法,那死锁可能出现,这种环境下系统可以提供:
需要从如下两个方面分别考虑这个问题:
1.每种资源类型只有单个实例
检测算法:用等待图,它是资源分配图的一个变形,从资源分配图中删除所有资源类型节点,合并适当边,就能得到等待图。
如等待图中有环,系统中存在死锁。
为检测死锁,系统需要维护等待图,并周期性的调用在图中进行搜索环的算法
2.每种资源类型可有多个实例
类似于银行家算法
3.应用检测算法
何时调用算法取决于:
每次资源请求调用检测算法
每次资源请求不被允许时调用检测算法
当检测算法确定已有死锁是,需要打破。打破死锁有两个选择,一个是简单的终止一个或多个进程来打破循环等待;另一个是从一个或多个进程那里抢占一个或多个资源
1.终止进程
两种方法:
如果采用部分终止,我们应该终止造成最小代价的进程,许多因素影响了选择哪个进程:
2.资源抢占
通过抢占资源以取消死锁,逐步从进程中抢占资源给其他进程使用,直到死锁被打破为止。
需要处理三个问题
全部0条评论
快来发表一下你的评论吧 !