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

详解银行家算法「建议收藏」简述:银行家算法是一种可以避免死锁的方法就是以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源就相当于用户向银行家贷款。实现方法:为保证资金的安全,银行家规定:(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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Android源码在线查看网站

    Android源码在线查看网站安卓社区https://www.androidos.net.cn/sourcecode(推荐)AndroidXRefhttp://androidxref.com/安卓特性(包括历史版本):https://developer.android.google.cn/

    2022年7月20日
  • pythonrandom函数用法_python标准库总的random函数用法[通俗易懂]

    pythonrandom函数用法_python标准库总的random函数用法[通俗易懂]Python标准库中的random函数,可以生成随机浮点数、整数、字符串,甚至帮助你随机选择列表序列中的一个元素,打乱一组数据等。random中的一些重要函数的用法:1)、random()返回0…

    2022年6月3日
  • 数据库设计概念结构设计_数据库设计典型实例

    数据库设计概念结构设计_数据库设计典型实例文章目录数据库设计概念设计结构概念结构设计ER模型的基本元素实体/实体集属性区别实体和属性联系二元联系的关系1:11:nm:n一元联系1:11:nm:n三元联系采用ER模型的概念设计设计局部ER模型例题设计全局ER模型全局ER模型的优化数据库设计数据库设计:构造最优的数据模型,建立数据库及其应用系统的过程数据库设计的好坏非常重要概念设计结构概念设计的目标是产生反映用户需求的数据库概念结构,即概念模型概念模型具有硬件独立、软件独立的特点处于一个桥梁作用概念设计的主要步骤

    2022年10月12日
  • 空间矢量脉冲宽度调制(SVPWM)Simulink仿真教程

    空间矢量脉冲宽度调制(SVPWM)Simulink仿真教程目录SVPWM仿真主体结构扇区选择模块XYZ计算模块矢量作用模块切换时间判断模块三角波模块开关信号模块输出信号模块输出结果SVPWM参考文献​SVPWM仿真主体结构扇区选择模块原理基于原理搭建基于原理的s函数扇区输出结果XYZ计算模块原理基于原理搭建模块仿真结果矢量作用模块原理基于原理搭建模块仿真结果切换时间判断模块原理…

    2022年10月31日
  • MySQL数据库备份和恢复方案小结[通俗易懂]

    MySQL数据库备份和恢复方案小结[通俗易懂]这两天在调研MySQL数据库的备份和恢复方案,备份对象是对大量Innodb表,或者加上少量的MyISAM表。 InnoDB备份常见问题:文件一致性:数据文件、缓存、日志文件必须保持严格一致。加锁的方法没法保证一致性,因为InnoDB后台刷新数据是异步进行的。数据一致性:不能一次锁住一张表,这个备份的是不同时刻的表数据;如果一次锁住所有表,innodb的mvcc机制会增加undo日志…

    2022年6月6日
  • 通过Java实现求水仙花数「建议收藏」

    通过Java实现求水仙花数「建议收藏」用户输入一个数,判断是否是”水仙花数”,所谓”水仙花数”是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个”水仙花数”,因为153=1的三次方+5的三次方+3的三次方。程序同用户交互是通过Scanner来实现的,jdk中封装了一个类Scanner,该类的职责就是接收键盘的输入值,并保存到程序的变量中,体现了程序和用户的交互功能,适合新手学习。

    2022年7月8日

发表回复

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

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