在了解银行家算法之前,我们先了解一下死锁的概念和它的相关知识。
死锁
概念 :多个进程相互等待,互不相让,导致所有进程无限期等待。
死锁分为 资源死锁 和通信死锁。
资源死锁:每个进程都在等待其他进程释放资源。资源死锁时最常见的死锁类型。
通信死锁:由于信息丢失,导致通信双方互相等待对方发送消息。一般可以设置超时时间来解决。
资源死锁条件
1)互斥条件:一个进程不能被两个以上的进程同时占有。
2)占有和等待:已经得到某个资源的进程可以申请新的资源。
3)不可抢占条件:已经分配给一个进程的资源不能被强制性抢占,他只能被占有它的进程显式释放。
4)环路等待:死锁发生时,系统中一定有两个及两个以上的进程形成一条环路。
死锁处理
1)忽略问题。
2)检测死锁并恢复
3)避免死锁
4)防止死锁发生
今天我们要说的就是死锁避免的策略—银行家算法
银行家算法是最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态的申请资源,但系统在进行资源分配之前,应该先计算此次分配资源的安全性,若果分配不会导致系统进入不安全状态,则分配,否则等待。
先说一下算法中需要的数据结构:
1.可利用资源向量Available:他是一个一维数组。其中的每一个元素代表一类可利用的资源数目。它的数值会根据资源的分配和回收发生改变。比如Available[i]=k,则说明系统现在i类资源有k个。
2.最大需求矩阵Max:只是一个矩阵,代表多个进程对每个资源的最大需求量,比如Max[i,j]=k,代表第i个进程对第j个资源最大需求k个。
3.分配矩阵Allocation:只是一个矩阵。代表不同进程已经分配的各种资源数。
4.需求矩阵Need:是一个矩阵,代表每个进程还需要资源的数目。
其中三个矩阵有这样的关系:Max[i,j]=Allocation[i,j]+Need[i,j]
算法描述
设 Request;是进程Pi的请求向量,如果 Requesti[j] = K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检査:
(1) 如果 **Requesti[j] ≤ Need[i,j]**便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。
(2) 如果 **Requesti[j] ≤ Available[j],**便转向步骤(3);否则,表示尚无足够资源,Pi须等待。
(3) 系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值
Available[i] = Available[j] - Requesti[j];
Allocation[i,j] = Allocation[i,j] + Requesti[j];
Need[i,j] = Need[i,j] - Requesti[j];
(4) 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
安全性算法:
系统所执行的安全性算法可描述如下:
(1) 设置两个向量:①工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work = Available;② **Finish:**它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做 Finish[i] = false;当有足够资源分配给进程时,再令Finish[i] = true。
(2) 从进程集合中找到一个能满足下述条件的进程
① Finish[i] = false;
② Need[i,j] ≤ Work[j];
若找到,执行步骤(3),否则,执行步骤(4)。
(3)当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[i] = Work[j] + Allocation[i,j];
Finish[i] = true;
go to step 2;(goto语句不推荐使用 _ )
(4)如果所有进程的 Finish[i] =true都满足,则表示系统处于安全状态;否则,系统处于不安全状态。
代码设计思想
这个程序用C语言实现的,涉及了部分c++知识。
下面说一下结构体设计,首先最大需求矩阵,需求矩阵,已分配矩阵,工作矩阵,work+allocation矩阵,都用一个二维数组来表示。Finish和available向量用一个一维数组来表示。
方法和接口设计如下:每个接口均有注释,可结合注释来看。
请求资源函数和安全性算法函数返回值设置为int型,方便调用。请求资源函数调用安全型判断函数。
具体设计如下:
全代码分为四个模块:1.初始化 2.安全性检查 3.请求资源 4.退出.
在初始化中,分别对Max,Allocation,Need矩阵进行初始化,其中Need[i][j]=Max[i][j]-Allocation[i][j];.用两次for循环实现。
2、安全性检查中,首先初始化work[],把available[]赋值给它,初始化完成。然后再Need矩阵中寻找满足Need[i][j]<work[j]的进程,找到后,更新work矩阵的值,以及work+available矩阵的值,并将进程号加入安全序列,标志位给true,没找到,标志位给false,记录true的个数。设置返回值返回。
3、请求资源时,先判断这两个条件
如果满足,退出,不能请求资源。否则,进入到预分配,更新available向量,Need,allocation的值,调用安全性算法,**通过其返回值,判断ture的个数是否等于进程数,**等于,则可已分配资源。否则,把试分配的资源还给系统。当进程所需资源数已经全部得到满足后,应该回收此资源。
流程图
运行结果
如图,刚开始初始化所有进程资源请情况表如下 此时Available向量是 {3,3,2}
此时 安全序列是 1 3 0 2 4
当进程1申请资源{1,0,2}时,判断两个条件,满足后试分配,申请资源成功。此时安全序列是1 3 0 2 4
继续申请,给进程三申请{1,1,0},发现其大于自身Need,则申请失败。此时Available值为{2 3 0},因为刚才给p1分配了{1 0 2}
接下来给进程2申请{4,0,0},经过检测,发现它大于Available,则申请失败 。
来源:CSDN
作者:野猫 吉吉
链接:https://blog.csdn.net/cat_little_cat/article/details/104065605