博客 死锁处理方法 里讲述了4种处理操作系统死锁的方法,分别是
- 死锁预防
- 死锁避免
- 死锁检测和修复
- 撒手不管法
其中在讲死锁避免时,提到了安全序列<P1,P2,P3,...,Pn>,所有进程按照 Pi要求的资源≤当前可用资源+所有Pj持有资源,其中j<i 的条件进行排序,如果能排出这样一个序列,那么最终序列中的所有进程都能获得所需的资源。
如果存在这样一个安全序列,那称电脑处于安全状态,处于安全状态的操作系统一定不会发生死锁;
如果不存在这样的一个安全序列,那称电脑处于不安全序列,只有处于不安全状态的操作系统才有可能发生死锁。
讲了一些储备知识之后,我们来具体介绍银行家算法吧。
它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行,因此得名银行家算法。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金。
如果能同时满足以上4点要求,银行才肯给客户贷款,在这样的描述中:
- 银行家→操作系统
- 资金→资源
- 客户→要申请资源的进程/线程
从银行家的比喻回到操作系统里,是说,系统允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。
下面讲述几个矩阵或向量,后面需要用到:
1)可利用资源向量Available
是1个含有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]
银行家算法的基本思想是:在分配资源之前,先判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。
那么问题的关键在于,如何判断系统是安全的?
设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断:
- 如果REQUEST [cusneed] [i]<= NEED[cusneed][i],意思是该进程想申请的资源数≤还能申请的资源数(客户还想借的资金和之前已经借的资金加起来,不能超过一开始承诺的最大资金需求量),满足则转2;否则,出错。
- 如果REQUEST [cusneed] [i]<= AVAILABLE[i],意思是该进程想申请的资源数≤系统可利用的资源数(银行还剩足够的钱可以借给该客户),满足则转3;否则,等待。
- 系统试探分配资源,修改相关数据:AVAILABLE[i]-=REQUEST[cusneed][i];ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];NEED[cusneed][i]-=REQUEST[cusneed][i],意思是假如把资金借给该客户了,那么银行里还剩下的空闲资金,已经借给该客户的总资金,和该客户还能借的最大资金,都需要更新一下;
- 系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,相关数据变回原来的状态,进程等待。
这就是判断的方法。
可能有些读者对第4步的执行安全性检查有疑问,并不知道怎样才算是处于安全状态。那么下面讲述一下具体步骤:
- 设置两个工作向量Work=AVAILABLE (AVAILABLE表示可利用资源向量,上文提到)和 FINISH,FINISH为真表示进程已经完成、结束,为假表示进程还需要部分资源才能继续执行,还没结束;
- 从进程集合中找到一个满足下述条件的进程,FINISH==false(该进程还需要资源);NEED<=Work(所需要的资源≤剩余的空闲资源);如找到,执行3;否则,执行4;
- 进程获得它想要的资源,顺利执行直至完成,从而释放资源。然后Work=Work+ALLOCATION(进程已经结束,也要停止占用资源了,所以剩余的空闲资源数需要调整一下);Finish=true(进程已经结束了,需要把FINISH改为真);回到2;
- 如所有的进程Finish= true,则表示安全;否则系统不安全。