背景简介:
在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。
安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。(即在分配过程中,不会出现某一进程后续需要的资源量比其他所有进程及当前剩余资源量总和还大的情况)
注:存在安全序列则系统是安全的,如果不存在则系统不安全,但不安全状态不一定引起死锁。
原理过程:
系统给当前进程分配资源时,先检查是否安全:
在满足当前的进程X资源申请后,是否还能有足够的资源去满足下一个距最大资源需求最近的进程(如某进程最大需要5个单位资源,已拥有1个,还尚需4个),若可以满足,则继续检查下一个距最大资源需求最近的进程,若均能满足所有进程,则表示为安全,可以允许给当前进程X分配其所需的资源申请,否则让该进程X进入等待。
(注:检查过程中,每拟满足一个进程,则进行下个检查时,当前可用资源为回收上一个进程资源的总值,每满足一个进程表示此进程已结束,资源可回收。)
如图:
算法过程:
Available[ ]矩阵数组表示某类资源的可用量
Claim[ i ][ j ]表示进程Pi最大需要Rj类资源的数量
Allocation[ i ][ j ]表示Pi已占有的Rj类资源数量
Need[ i ][ j ]表示Pi尚需Rj类资源的数量
-------------------------------------------------------------------
Need[ i ][ j ]=Claim[ i ][ j ]—Allocation[ i ][ j ]
-------------------------------------------------------------------
Request[ i ]表示进程Pi进程的申请向量,如 Request[ i ][ j ]=m 表示Pi申请m个Rj类资源
对于当前进程Pi X
(1) 检查if( Request[ i ][ j ]<=Need[ i ][ j ] ) goto (2)
else error(“进程 i 对资源的申请量大于其说明的最大值 ”);
(2) 检查 if ( Request[ i ][ j ]<=Available[ j ] ) goto (3)
else wait() ; /*注意是等待!即在对后续进程的需求资源判断中,若出现不符合的则安全检查结束,当前进程进入等待*/
(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 ]
(4)安全检查,若检查结果为安全,则(3)中执行有效,否则分配作废,使该Pi进程进入等待
检查算法描述:
向量Free[ j ]表示系统可分配给各进程的Rj类资源数目,初始与当前Available等值
向量Finish[ i ]表示进程Pi在此次检查中是否被满足,初始均为false 当有足有资源可分配给进程时,
Finish[ i ]=true, Pi完成并释放资源(Free[ j ]+=Allocation[ i ][ j ])
1) 从进程队列中找一个能满足下述条件的进程Pi
①、Finish[ i ]==false,表示资源未分配给Pi进程
②、Need[ i ][ j ]<Free[ j ],表示资源足够分配给Pi进程
2) 当Pi获得资源后,认为Pi完成,释放资源
Free[ j ]+=Allocation[ i ][ j ];
Finish[ i ]=true;
goto Step 1);
例:
int trueSum=0, i=0 ; boolean Flag=true;
while( trueSum<P.length-1 && Flag==true ){
i=i%P.length;
if( Finish[ i ]==false ){
if(Need[ i ][ j ]<Free[ j ]){
Free[ j ]+=Allocation[ i ][ j ];
Finish[ i ]=true;
trueSum++;
i++;
}else{
Flag=false;
}
} }
if( Flag==false)
检查不通过,拒绝当前进程X的资源申请
else
检查通过,允许为当前进程X分配资源
即若可达到Finish[ 0,1,2,......n ] ==true 成立则表示系统处于安全状态
例:
有5个进程{P1,P2,P3,P4,P5} 。4类资源{R1,R2,R3,R4} 各自数量为6、3、4、2
T0时刻各进程分配资源情况如下
T0时刻为安全状态,存在安全序列{P4,P1,P2,P3,P5} 如下:
(银行家算法在避免死锁角度上非常有效,但是需要在进程运行前就知道其所需资源的最大值,且进程数也通常不是固定的,因此使用有限,但从思想上可以提供了解,可以转换地应用在其他地方)