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

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


相关推荐

  • Python 实现搭建本地IP代理池

    Python 实现搭建本地IP代理池本文仅供学习交流使用,如侵立删!联系方式及demo下载见文末爬取:66ip免费代理defget_66ip(self):”””抓取66ip免费代理:return:”””forindexinrange(1,self.sixsix_url_range):count=0province=”url=’http

    2022年6月10日
    42
  • 代码主题darcula_如何在带有Darcula主题的黑暗模式下使用NetBeans「建议收藏」

    代码主题darcula_如何在带有Darcula主题的黑暗模式下使用NetBeans「建议收藏」本文概述默认情况下,NetBeans仅为代码编辑器提供一个深色高亮主题,没有什么令人愉快的”城市之光”:如你所见,它仍然使用NetBeans的默认light主题,简直太可怕了。在本文中,我们将向你展示如何为NetBeans安装和使用最佳的深色主题之一,类似于PHPStorm的深色主题。1.下载DarculaLAF(Look&Feel)对于NetBeans,最好的深色主题是Dar…

    2022年6月27日
    41
  • Mac OS mysql 启动命令

    Mac OS mysql 启动命令在MacOSX启动和停止MySQL服务的命令  启动MySQL服务  sudo/usr/local/mysql/support-files/mysql.serverstart 停止MySQL服务  sudo/usr/local/mysql/support-files/mysql.server stop 重启MySQL服务  sudo…

    2022年5月21日
    47
  • SpringBoot自动配置原理总结

    SpringBoot自动配置原理总结SpringBoot自动配置原理总结

    2022年8月21日
    15
  • linux关闭防火墙命令firewall

    linux关闭防火墙命令firewall在外部访问 CentOS 中部署应用时 需要关闭防火墙 关闭防火墙命令 systemctlsto service 开启防火墙 systemctlsta service 关闭开机自启动 systemctldis service 开启开机启动 systemctlena service

    2026年3月18日
    2
  • restsharp.dll_restbed

    restsharp.dll_restbed一、RestSharp简绍RestSharp是一个轻量的,不依赖任何第三方的组件或者类库的Http的组件。RestSharp具体以下特性;1、支持.NET3.5+,Silverlight4,WindowsPhone7,Mono,MonoTouch,MonoforAndroid,CompactFramework3.5等  2、通过NuGet方便引入到任何项目(In…

    2025年10月9日
    4

发表回复

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

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