银行家算法

银行家算法

在了解银行家算法之前,我们先回顾一下死锁产生的条件和处理方法

死锁产生的四个必要条件

1、互斥条件:一个资源每次只能被一个线程使用
2、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
3、不剥夺条件:进程已获得的资源,在未使用之前,不能强行剥夺
4、循环等待条件:若干进程之间形成一种头尾相连接的循环等待资源关系

死锁的解除与预防

解决死锁的三种途径:预防、避免、检测与恢复。那么如何避免死锁,就是今天所要踢到的经典避免死锁方法——银行家算法。

避免死锁(银行家算法)

避免死锁的策略中,允许进程进行资源的动态的申请,系统在资源分配先进行预分配,先计算资源分配的安全性,不会导致系统进不到不安全的状态,系统会将资源真正的分配给进行。

银行家算法

当一个进程申请使用资源的时候,银行家算法通过先 试探 分配给该进程资源,
然后通过安全性算法判断分配后的系统是否处于安全状态,若不安全则试探分配作废,让该进程继续等待。

在这里插入图片描述

首先银行家算法的进程:
包含进程pi的需求资源的数量M(每个进程最大的需求你资源数量,MAX)
已分配的进程的资源A(Allocation)
还需要的资源数量N(Need=M-A)
系统资源池中空闲的资源数量:Avaliable(Available+已分配的资源数量A=系统中资源的总量)
在这里插入图片描述
在这里插入图片描述
通过安全性分析:找到了安全性序列:P0\p3\p4\p1\p2,当前的资源分配时安全的,即可以给线程进程资源分析,真正开始资源分配。

那么安全性分析的过程是什么呢?

安全性分析主要是通过安全性算法实现的!

安全性算法流程图:

在这里插入图片描述
(1) 设置两个工作向量Work=AVAILABLE;FINISH

(2) 从进程集合中找到一个满足下述条件的进 程,

FINISH==false;

NEED<=Work;

如找到,执行(3) ; 否则,执行(4)

(3) 设进程获得资源,可顺利执行,直至完 成,从而释放资源。

Work+=ALLOCATION;

Finish=true;

GOTO 2

(4) 如所有的进程Finish= true ,则表 示安全;否则系统不安全。

操作系统安全状态和不安全状态:

安全序列是指一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源

量之和。
如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。
不存在一个安全序列。不安全状态不一定导致死锁。

银行家算法代码实现

/**
 * 银行家算法实现
 */
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;
        if (!(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中每类资源数量减去每类资源的请求数量
        }
        boolean flag = checkSafe(available[0], available[1], available[2]);//进行安全性检查并返回是否安全
        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;
        }
    }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值