详解银行家算法「建议收藏」

详解银行家算法「建议收藏」简述:银行家算法是一种可以避免死锁的方法就是以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源就相当于用户向银行家贷款。实现方法:为保证资金的安全,银行家规定:(1)当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;(即当资源池中剩余的可利用资源>=线…

大家好,又见面了,我是你们的朋友全栈君。

简述:银行家算法是一种可以避免死锁的方法

就是以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源就相当于用户向银行家贷款。
实现方法:
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(即当资源池中剩余的可利用资源 >= 线程还需要的资源时,就可以将可利用资源分配给此线程)
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(线程可以请求分配资源,但是请求的资源总数不能超过资源池中剩余的可利用资源)
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(当线程池中的资源暂时不满足当前的线程所需时,将此线程先暂时搁置,先将资源分配给能够满足的需求的其他线程,等到线程池中的资源足够满足先前搁置的线程时,在将资源分配给搁置的线程)
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金。
(当线程拿到所需要的所有资源,运行结束后,将自身所有的资源放回资源池中)

实例讲解

下图共有5个线程,4种资源,已经将线程池中的部分资源分配
在这里插入图片描述
分析过程:
资源池中剩余的可用资源量为1 6 2 2,现开始将可用资源量试分配给待运行的线程。
P0已经拥有了0 0 3 2,还需要0 0 1 2,将可以利用的资源量1 6 2 2分配给P0,资源池中就只剩下了1 6 1 0的资源,但P0拥有了0 0 4 4就开始运行,结束后释放自己的所有拥有的资源至资源池中,此时线程池中的总资源量为1 6 5 4,将P0的状态置为true。
P1已经拥有了1 0 0 0,还需要1 7 5 0,接下来本该将资源池中的资源分配给P1,但是经过比较,1 6 5 4 < 1 7 5 0,资源池中的资源不够分给P1,所以先将P1搁置,状态置为false
P2已经拥有了1 3 5 4,还需要2 3 5 6,接下来本该将资源池中的资源分配给P2,但是经过比较,1 6 5 4 < 2 3 5 6,资源池中的资源不够分给P2,所以先将P2搁置,状态置为false
P3已经拥有了0 3 3 2,还需要0 6 5 2,将可以利用的资源量1 6 5 4分配给P3,资源池中就只剩下了1 0 0 2的资源,但P3拥有了0 9 8 4就开始运行,结束后释放自己的所有拥有的资源至资源池中,此时线程池中的总资源量为1 9 8 6,将P3的状态置为true。
P4已经拥有了0 0 1 4,还需要0 6 5 6,将可以利用的资源量1 9 8 6分配给P4,资源池中就只剩下了1 3 3 0的资源,但P4拥有了0 6 6 10就开始运行,结束后释放自己的所有拥有的资源至资源池中,此时线程池中的总资源量为1 9 9 10,将P4的状态置为true。
然后回到搁置的线程处,重新试着分配。 详解银行家算法「建议收藏」
第二个问题如下图:
在这里插入图片描述
代码实现:
实现过程中当部分线程资源得不到满足被暂时搁置后,要等到它的下一个线程状态置true时,从头开始再次进行试分配。

import java.util.Scanner;
public class Banker { 
   
    int available[] = new int[]{ 
   3,3,2};//可得到的资源
    int max[][] = new int[][]{ 
   { 
   7,5,3},{ 
   3,2,2},{ 
   9,0,2},{ 
   2,2,2},{ 
   4,3,3}};//每个进程最大资源数
    int allocation[][] = new int[][]{ 
   { 
   0,1,0},{ 
   2,0,0},{ 
   3,0,2},{ 
   2,1,1},{ 
   0,0,2}};//每个进程目前拥有的资源数
    int need[][] = new int[][]{ 
   { 
   7,4,3},{ 
   1,2,2},{ 
   6,0,0},{ 
   0,1,1},{ 
   4,3,1}};//每个进程需要的资源数
    void showData() { 
   
    //展示数据输出每个进程的相关数
        System.out.println("进程号 Max All Need ");
        System.out.println(" A B C A B C A B C");
        for(int i = 0;i<5;i++){ 
   
            System.out.print(i+" ");
            for(int m = 0;m<3;m++) System.out.print(max[i][m]+" ");
            for(int m = 0;m<3;m++) System.out.print(allocation[i][m]+" ");
            for(int m = 0;m<3;m++) System.out.print(need[i][m]+" ");
            System.out.println();
        }
    }

    boolean change(int inRequestNum,int inRequest[])//分配数据
    { 
   
        int requestNum = inRequestNum;
        int request[] = inRequest;
        // for(int i=0;i<3;i++)System.out.println("修改前available"+available[i]);
        if(!(request[0]<=need[requestNum][0]&&request[1]<=need[requestNum][1]&&request[2]<=need[requestNum][2]))
        { 
   
            //request[0]<=need[requestNum][0]
            //request[1]<=need[requestNum][1]
            //request[2]<=need[requestNum][2]
            //每一类请求资源小于当前线程need的资源数
            System.out.println("请求的资源数超过了所需要的最大值,分配错误");
            return false;
        }
        if((request[0]<=available[0]&&request[1]<=available[1]&&request[2]<=available[2])==false)
        { 
   
            //当前线程的每一类请求资源小于等于资源池对应资源的数量
            System.out.println("尚无足够资源分配,必须等待");
            return false;
        }

        for(int i = 0;i<3;i++)//试分配数据给请求的线程
        { 
   
            available[i] = available[i]-request[i];
            //资源池的每类资源减去每类请求资源数量
            allocation[requestNum][i] = allocation[requestNum][i] + request[i];
            //当前线程allocation中每类资源加上每类资源请求数量
            need[requestNum][i] = need[requestNum][i] - request[i];
            //当前线程need中每类资源数量减去每类资源的请求数量
        }
// for(int i=0;i<3;i++)System.out.println("修改后available"+available[i]);
        boolean flag = checkSafe(available[0],available[1],available[2]);//进行安全性检查并返回是否安全
// System.out.println("安全性检查后"+flag);
        if(flag==true)
        { 
   
            System.out.println("能够安全分配");
            return true;
        }
        else//不能通过安全性检查 恢复到未分配前的数据
        { 
   
            System.out.println("不能够安全分配");
            for(int i = 0;i<3;i++)
            { 
   
                available[i] = available[i]+request[i];
                allocation[requestNum][i] = allocation[requestNum][i] - request[i];
                need[requestNum][i] = need[requestNum][i] + request[i];
            }
            return false;
        }
    }
    boolean checkSafe(int a,int b,int c)//安全性检查
    { 
   
        int work[] = new int[3];
        work[0] = a;
        work[1] = b;
        work[2] = c;
        int i=0;
        boolean finish[] = new boolean[5];
        while(i<5)//寻找一个能够满足的认为完成后才去执行下一进程
        { 
   
            if(finish[i]==false&&need[i][0]<=work[0]&&need[i][1]<=work[1]&&need[i][2]<=work[2])
            { 
   //找到满足的修改work值,然后i=0,重新从开始的为分配的中寻找
                System.out.println("分配成功的是"+i);
                for(int m = 0;m<3;m++)
                    work[m] =work[m] + allocation[i][m];
                finish[i] = true;
                i=0;
            }
            else//如果没有找到直接i++
                i++;
        }
        for(i=0;i<5;i++)//通过finish数组判断是否都可以分配
        { 
   
            if(finish[i]==false)
                return false;
        }
        return true;
    }
    public static void main(String[] args)
    { 
   
        Banker bank = new Banker();
        bank.showData();
        //请求线程资源存放的数组
        int request[] =new int[3];
        int requestNum;
        String source[] = new String[]{ 
   "A","B","C"};
        Scanner s = new Scanner(System.in);
        String choice = new String();
        while(true)//循环进行分配
        { 
   
            System.out.println("请输入要请求的进程号(0--4):");
            requestNum = s.nextInt();
            System.out.print("请输入请求的资源数目");
            for(int i = 0;i<3;i++)
            { 
   
                System.out.println(source[i]+"资源的数目:");
                request[i] = s.nextInt();
            }
            bank.change(requestNum, request);
            System.out.println("是否再请求分配(y/n)");
            choice = s.next();
            if(choice.equals("n"))
                break;
        }
    }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/163227.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • php 设置error_reporting(0)和ini_set(‘display_errors’, 0)之后,还是显示错误「建议收藏」

    php 设置error_reporting(0)和ini_set(‘display_errors’, 0)之后,还是显示错误

    2022年2月8日
    44
  • 国内十大正规现货交易平台排名(2021版榜单)

    国内十大正规现货交易平台排名(2021版榜单)现货亦称实物,指可供出货、储存和制造业使用的实物商品。可供交割的现货可在近期或远期基础上换成现金,或先付货,买方在极短的期限内付款的商品的总称。期货的对称。随着互联网的出现,世界已慢慢变成地球村,建立在信息化基础上的现货电子交易走上新经济的舞台。现货电子交易(也称为大宗商品电子交易,或现货仓单交易)是以现货仓单为交易的标的物,采用计算机网络进行的集中竞价买卖,统一撮合成交,统一结算付款,价格行情实时显示的交易方式。国内不少投资者对现货交易还不是太了解,下面小编为您介绍“国内十大正规现货交易平台排名(20

    2022年6月15日
    54
  • 半小时实现Java手撸网络爬虫框架!!(附完整源码,建议收藏)

    半小时实现Java手撸网络爬虫框架!!(附完整源码,建议收藏)半小时实现Java网络爬虫,附完整源码,冰河强烈建议收藏!!

    2022年8月22日
    3
  • vim编辑器重要快捷键及vim设置「建议收藏」

    vim编辑器重要快捷键及vim设置「建议收藏」1.全选:ggVG2.跳转到文本最后一行:shift+g3.跳转到文本第一行:gg4.跳转到光标所选行的行首位置:05.跳转到光标所选行的行尾位置:shift+46.全部替换(替换无需确认)::%s/src/dst/g7.全部替换(每次替换需要确认)::%s/src/dst/gc8.查找:/string9.高亮显示查找到的内容::sethlsearch10.显示vim行号::setnu!11.到注释的开始:[/12.到注释的结束:]/13.撤销上一次操作:

    2022年9月1日
    3
  • n皇后问题 回溯法java_Java解决N皇后问题

    n皇后问题 回溯法java_Java解决N皇后问题问题描述:   要求在一个n×n的棋盘上放置n个皇后,使得它们彼此不受攻击。   按照国际象棋的规则,一个皇后可以攻击与之同一行或同一列或同一斜线上的任何棋子。   因此,n皇后问题等价于:要求在一个n×n的棋盘上放置n个皇后,使得任意两个皇后不在同一行或同一列或同一斜线上。一个皇后的攻击范围:                                    n皇后的解空间—完全n叉树…

    2022年9月30日
    0
  • 用perl获取可用的代理服务器地址

    用perl获取可用的代理服务器地址

    2021年8月12日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号