【银行家算法】

先引用一个例子:填表法解“银行家算法”问题

银行家算法( banker’s algorithm )由 Dijkstra(1065)提出。他将死锁的问题演示为一个银行家贷款的模型。
一个银行家向一群客户发放信用卡,每个客户有不同的信用额度。每个客户可以提出信用额度内的任意额度的请求,直到额度用完后再一次性还款。银行家承诺每个客户最终都能获得自己需要的额度。
所谓“最终”,是说银行家可以先挂起某个额度请求较大的客户的请求,优先满足小额度的请求,等小额度的请求还款后,再处理挂起的请求。这样,资金能够永远流通。
银行家算法可以用以下图表表示:
《【银行家算法】》
每个客户和银行家都有交易限额。银行家只能和限额小于自己限额的客户进行交易。一旦银行家的限额小于所有客户的限额,便发生了死锁。
如上图所示。银行家分别和客户1,客户2,客户3进行了交易。第一次交易时,所有客户的限额都小于银行家的限额,任何客户都可以实现借款;第二次交易时,客户3的限额大小银行家的限额,这时银行家会挂起客户3 的请求;第三次交易时,只有客户3可以进行交易,其它的交易都会被挂起。直到客户3还款后,银行家才会考虑处理其它客户的交易。

银行家算法其核心是:保证自己的限额至少不小于一个客户的限额。
我们可以用填表法来快速解决银行家算法。

建立一个二维表格:每列数据表示每次交易各个参与者的限额。这个表格第一列数据是银行家是客户的交易限额,每发生一次交易,增加一列,同时将银行家和发生交易的客户的限额减小。直到银行家的限额小于某个客户的限额时,交易不能继续进行。否则便发生死锁。
《【银行家算法】》

例题:
1、操作系统分配资源时的一个重要考虑是避免死锁的发生.若系统中有同类资源 16 个,由四个进程 P1、P2、P3 和 P4 共享该资源。已知 P1、P2、P3、P4 所需的资源总数分别为 8、5、9、6。各进程请求资源的次序如下表,若系统采用银行家算法为它们分配资源,那么(1)_依次申请分配会使系统进入不安全状态。
进程申请资源的情况

序号 进程 申请量
1 P1 6
2 P2 4
3 P3 5
4 P4 1
5 P1 1
6 P2 1
A.3、4 B.3、5 C.4、5 D.5、6

答案是c
我们初始化一个二维表格
《【银行家算法】》

到完成第三个请求到达的时候,资源只有一个了。此时只能满足p2的请求。所以,第四个和第五个请求会被系统挂起。第六个请求p2到达后会被处理。等p2事务结束释放资源后,系统会再处理挂起的请求,这样就不会发生死锁。一旦在第三步后将剩下的唯一的一个资源分配给其它的进程,(如请求4或请求5),则请求4和5可能会因需要不止一个资源而继续等待,则发生了死锁。

死锁的定义
一组相互竞争系统资源或进行通信的进程间的“永久”阻塞。(直白点,就是我占用你准备用的,你占用我准备用的,两者(或多者)互不相让,也不争抢,一直等待对方放手。)

死锁的条件
1. 互斥:一次只有一个进程可以使用一个资源。其他进程不能访问已分配给其他进程的资源。
2. 占有且等待:当一个进程等待其他进程时,继续占有已分配的资源。
3. 不可抢占:不能强行抢占进程已占有的资源。
4. 循环等待:存在一个闭合的进程链,每个进程至少占有此链中下一个进程所需的一个资源。

处理死锁的三种方法

  1. 采用某种策略消除死锁条件中的某个条件的出现(一般不会选择破坏互斥条件),来预防死锁
  2. 基于资源分配的当前状态做动态选择的避免死锁
  3. 试图检测死锁的存在并从死锁中恢复

这里主要写避免死锁的经典算法—银行家算法

原理部分:

银行家算法中涉及的数据结构

  1. 可利用资源向量Available。表示含有m个元素的数组,其中每一个元素表示一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目。
  2. 最大需求矩阵Max。这是一个n*m的矩阵,他定义了系统中n个进程中的每一个进程对m类资源的最大需求。
  3. 分配矩阵Allocation。这时一个n*m的矩阵,定义了系统中每一类资源当前已分配给每一进程的资源数。
  4. 需求矩阵Need。这是一个n*m的矩阵,表示每一个进程尚需的各类资源数。

银行家算法步骤:
设Request_i是进程Pi的请求向量,如果Request_i[j]=K,表示进程Pi需要K个Rj类资源。当Pi发出资源请求后,系统按照下面的步骤进行检查:

  1. 如果Request_i[j]<=Need[i,j],便转向步骤2;否则认为出错,因为它所需要的资源数已超过了它所宣布的最大值。
  2. 如果Request_i[j]<=Available[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];
  4. 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式的将资源分配给进程Pi,以完成此次分配;否则,将本次的试探分配作废,恢复原来的资源分配,让进程Pi等待。

    安全性算法:
    1.设置两个向量:1)工作向量Work,表示可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work=Available;2)Finish:表示系统是否有足够的资源分配给进程,使之运行完成。开始先做Finishp[i]=false;当有足够资源分配给进程时,在令Finish[i]=true。
    2.从进程集合中找到一个能满足下述条件的进程:
    1)Finish[i]=false;
    2)Need[i,j]<=Work[j]
    若找到,执行步骤3);否则,执行步骤4).
    3)当进程Pi获得资源后,可顺利执行,直到完成,并释放出分配给他的资源你,故应执行:
    Work[[j] = Work[j] + Allocation[i,j];
    Finish[i]=true;
    go to step2 ;
    4)如果所有进程的Finish[i]=true都满足,则表示系统处于安全状态;否则,系统处于不安全状态。

实现代码:
【C++】银行家算法的实现
参考:
计算机操作系统(第四版),汤小丹、梁小兵

    原文作者:银行家问题
    原文地址: https://blog.csdn.net/feng_zhiyu/article/details/80811518
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞