【算法精髓】银行家算法
前言
- 一、算法背景
- 二、算法原理
- 三、死锁
- 四、数据结构:
- 五、银行家算法:
- 1. 银行家算法之例:
- 附:参考博客:
附: 银行家算法经典教程视频
一、算法背景
在银行中,客户申请贷款的数量
是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量
,在满足所有贷款要求时,客户应及时归还·
。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统
,资金就是资源
,客户就相当于要申请资源的进程
。
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性
,若分配不会导致系统进入不安全状态,则分配,否则等待。
二、算法原理
我们可以把·操作系统看作是银行家
,操作系统管理的资源相当于银行家管理的资金
,进程向操作系统请求分配资源相当于用户向银行家贷款
。
为保证资金的安全,银行家规定:
- (1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
- (2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
- (3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
- (4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量
,如果系统现存的资源可以满足它的最大需求量
则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。
银行家算法
是一种用来避免操作系统死锁出现的有效算法
,所以在·详解银行家算法
之前,有必要简单介绍下死锁
的概念。
三、死锁
死锁
:是指两个或两个以上的进程在执行过程
中,由于竞争资源
或者由于彼此通信
而造成的一种阻塞
的现象,若无外力作用,它们都将无法推进下去。 此时称系统处于死锁状态
或系统产生了死锁
,这些永远在互相等待的进程
称为死锁进程。
死锁的发生必须具备以下四个必要条件:
- 1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
- 2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
- 3)不抢占条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
- 4)循环等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
避免死锁算法
中最有代表性的算法就是Dijkstra E.W 于1968年提出的银行家算法
,银行家算法是避免死锁的一种重要方法,防止死锁的方法就是·
:确保上述四个条件之一不出现,则系统就不会发生死锁。
为实现银行家算法,系统必须设置若干数据结构
,同时要解释银行家算法,必须先解释操作系统安全状态
和不安全状态。
安全序列
:是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。安全状态
:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安`全状态。安全状态一定是没有死锁发生。不安全状态
: 不存在一个安全序列。不安全状态不一定导致死锁。
四、数据结构:
- 1)可利用资源向量Available:是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。
- 2)最大需求矩阵Max
这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。 - 3)分配矩阵Allocation
这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的 数目为K。 - 4)需求矩阵Need
这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
·下面是三者之间的关系:
Need[i,j]=Max[i,j]-Allocation[i,j]
五、银行家算法:
设Request(i)是进程Pi的请求向量,如果Request(i)[j]=k,表示进程Pi需要K个R(j)类型的资源。当Pi发现资源请求后系统将进行下列步骤
(1)如果Request(i)[j] <= Need[i,j],边转向步骤2),否则认为出错,因为它所请求的资源数已超过它所宣布的最大值。
(2)如果Request(i)[j] <= Available[i,j],便转向步骤3),否则,表示尚无足够资源,Pi需等待。
(3)系统试探着把资源分配给进程Pi,并需要修改下面数据结构中的数值;
Available[j] = Available[j] - Request(i)[j];Allocation[i,j] = Allocation[i,j] + Request(i)[j];Need[i,j] = Need[i,j] - Request(i)[j];
说了这么多基本的概念,下面就让我们通过实际案例来体会银行算法吧。
1. 银行家算法之例:
解析:
从图中数据我们可以利用银行家算法的四个数据结构,来描述当前的系统状态
因为系统资源R=(17,5,20)而系统分配给这几个线程的资源为Allocation=(15,2,17) 则可以求出Available=(2,3,3)
(1)在T0时刻,由于Availabel大于等于Need中 P5 所在行的向量,因此Availabel能满足 P5 的运行,在 P5 运行后,系统的状态变更为如下图所示:
因此,在T0时刻,存在安全序列:P5,P4,P3,P2,P1(并不唯一)
(2)P2请求资源,P2发出请求向量Request(i)(0,3,4),系统根据银行家算法进行检查;
① P2 申请资源Reuqest(i)(0,3,4)<=Need中 P2 所在行向量Need(i)(1,3,4)
② P2 申请资源Reuqest(i)(0,3,4)>=可以利用资源向量Availabel(2,3,3),所以,该申请不给于分配
(3)P4请求资源,P4发出请求向量Request(i)(2,0,1),系统根据银行家算法进行检查;
①Reuqest(i)(2,0,1)<= Need(i)(2,2,1)
② Reuqest(i)(2,0,1 <= Availabel(2,3,3)
③对 P4 的申请(2,0,1)进行预分配后,系统的状态为:
可利用资源向量Availabel=(0,3,2),大于Need中 P4 所在行的向量(0,2,0),因此可以满足 P4 的运行。P4 运行结束后,系统的状态变为:
同理依次推导,可计算出存在安全序列P4,P5,P3,P2,P1(并不唯一)
(4)P1请求资源,P1发出请求向量Request(i)(0,2,0),系统根据银行家算法进行检查;
①Request(i)(0,2,0)<= Need(i)(3,4,7)
② Request(i)(0,2,0)<= Availabel(2,3,3)
③对 P1 的申请(0,2,0)进行预分配后,系统的状态为:
由于Availabel不大于等于 P1 到 P5 任一进程在Need中的需求向量,因此系统进行预分配后
处于不安全状态,所以对于 P1 申请资源(0,2,0)不给予分配。
注意:因为(4)是建立在第(3)问的基础上的所以Available=(0,3,2)-(0,2,0)=(0,1,2)
总结:
通过上述的解释,我相信大家对理解这种类似的题目应该游刃有余了吧,如果实在不懂的话那我就进开头的网站,那里面有个专门讲这个银行家算法的案例,个人觉得比较详细
附:参考博客:
银行家算法学习 、
一张图说明银行家算法、
C++代码实现银行家算法 、
银行家算法