死锁避免——银行家算法

死锁
两个或者两个以上的线程在执行过程中由于竞争资源而造成的阻塞问题,若无外力作用,他们将无法推进下去,此时系统处于死锁状态。
安全序列
安全序列是指对当前申请资源的进程排出一个序列,保证按照序列分配资源完成进程,不会发生死锁问题
我们假设有进程P1,P2,…Pn
则安全序列要求满足:Pi(1<=i<=n)需要资源<=剩余资源 + 分配给Pj(1 <= j < i)资源

示例
ProcessAllocationNeedAvailable
P00 0 3 20 0 1 21 6 2 2
P11 0 0 01 7 5 0
P21 3 5 42 3 5 6
P30 3 3 20 6 5 2
P40 0 1 40 6 5 6

采用银行家算法

ProcessWorkAllocationNeedAvailable
P01 6 2 20 0 3 20 0 1 21 6 5 4
P31 6 5 40 3 3 20 6 5 21 9 8 6
P41 9 8 60 0 1 40 6 5 61 9 9 10
P11 9 9 101 0 0 01 7 5 02 9 9 10
P22 9 9 101 3 5 42 3 5 63 12 14 14

我们来分析一下银行家算法
现有资源为 1 6 5 4,P0 线程需要0 0 1 2,足够分配给它,我们分配给线程P0,等到P0 运行完回收资源,Avaliable 为1 6 5 4。
然后线程P1,需要资源1 7 5 0,Avaliable < Need,不分配
线程P2 需要资源2 3 5 6,Avaliable < Need,不分配
线程P3 需要资源0 6 5 2,分配给它然后回收资源,Avaliable 为1 9 8 6
线程P4 需要资源0 6 5 6,分配给它然后回收资源,Avaliable 为1 9 9 10
返回继续判断P1,需要资源1 7 5 0,分配给它然后回收资源,Avaliable 为2 9 9 10
然后P2,需要资源2 3 5 6,分配给它然后回收资源,Avaliable 为3 12 12 14
在这里插入图片描述
用java来实现一下银行家算法

package com.os;
import java.util.Scanner;

/**
 * Description:v银行家算法
 *
 * @author:仙女萌
 * @Date 2018/12/29 16:32
 */
public class BankerAlgorithm {
    private static Scanner scanner = new Scanner(System.in);
    //资源数量
    private int resource;
    //线程数量
    private int thread;
    //资源总数量
    private int max[];
    //剩余资源数量
    private int avilable[];
    //最大需求矩阵
    private int[][] applymax;
    //已分配资源数量
    private int[][] allocation;
    //还需要资源是数量
    private int need[][];
    boolean F[];
    /**
     * 一维数组的输入
     * @param n
     * @return
     */
    private int[] inputone(int n){
        int[] number = new int[n];
        for(int i = 0;i < resource;i++){
            number[i] = scanner.nextInt();
        }
        return number;
    }
    /**
     * 二维数组的输入
     * @param m
     * @param n
     * @return
     */
    private int[][] inputtwo(int m,int n){
        int[][] number = new int[m][n];
        for(int i = 0;i < m;i++){
            System.out.print("进程p"+i+":");
            for(int j = 0;j < n;j++){
                number[i][j] = scanner.nextInt();
            }
        }
        return number;
    }
    /**
     * 数组的初始化
     */
    public void init(){
        System.out.print("请输入资源数量:");
        resource = scanner.nextInt();
        System.out.print("请输入线程数量:");
        thread = scanner.nextInt();
        System.out.print("请输入最大资源数量:");
        max = inputone(resource);
        System.out.println("请输入每个线程最大申请资源总数");
        applymax = inputtwo(thread,resource);
        System.out.println("请输入资源分配情况");
        allocation = inputtwo(thread,resource);
        //剩余资源
        avilable = max.clone();
        for(int i = 0;i < resource;i++){//资源个数
            for(int j = 0;j < thread;j++){//线程个数
                avilable[i] -= allocation[j][i];
            }
        }
        need = new int[thread][resource];
        //还需要资源need = apply-allocation
        for(int i = 0;i < thread;i++){
            for(int j = 0;j < resource;j++){
                need[i][j] = applymax[i][j] - allocation[i][j];
            }
        }
        F = new boolean[thread];
        show();
        System.out.println("安全性检查");
        int[] work = avilable.clone();
        safe(work,allocation,need);
    }
    /**
     * 输出
     */
    private void show(){
        int[] work = avilable.clone();
       //最大资源数量
        System.out.print("资源总数:");
        for(int i = 0; i < resource; i++){
            System.out.print(max[i]+"  ");
        }
        System.out.println();
        System.out.print("可利用资源向量:");
        for(int j = 0;j < resource;j++){
            System.out.print(work[j]+" ");
        }
        System.out.println();
        System.out.println("NAME"+"\t\t"+"MAX"+"\t\t"+"ALLOCATION1"+"\t\t"+"NEED");
        for(int i = 0 ;i < thread;i++){//线程
                System.out.print("p"+i+"\t\t\t");
           for(int j = 0;j <resource;j++){
               System.out.print(applymax[i][j]+" ");
           }
            System.out.print("\t\t");
            for(int j = 0;j < resource;j++){
                System.out.print(allocation[i][j]+" ");
            }
            System.out.print("\t\t");
            for(int j = 0;j <resource;j++){
                System.out.print(need[i][j]+" ");
            }
            System.out.println();
        }
    }
    /**
     * 安全性算法
     * @return
     */
    public boolean safe(int[] work,int[][] allocation,int[][] need){
        boolean s = true;
        int count = 0;
        int count1 = -1;
        for(int i = 0;i <thread;i++){
            F[i] = false;
        }
       // System.out.println("还原finish");
        System.out.println("name"+"\t\t"+"WORK"+"\t\t"+"NEED"+"\t\t"+"ALLOCATION"+"\t\t\t"+"WORK+ALLOCATION"+"\t\t"+"FINISH");
        int way[] = new int[thread];
        for(int i = 0;i < thread;i++) {
            s = true;
       //判断资源是否足够分配
            for (int j = 0; j < resource; j++) {
                if (work[j] < need[i][j]) {//avaliable <need
                    s = false;
                    break;
                }
            }
            // System.out.println(i+"检查完毕  s =="+s+" "+"F[i] ==" +F[i]);
            //资源足够分配,那么就分配资源
            if (s == true && F[i] == false) {
                F[i] = true;
                way[count++] = i;
                System.out.print("p"+i+"\t\t\t");

                for (int j = 0; j < resource;j++) {
                    System.out.print(work[j]+" ");
                }
                System.out.print("\t\t");
                for (int j = 0; j < resource; j++) {
                    System.out.print(need[i][j]+" ");
                }
                System.out.print("\t\t");
                for (int j = 0; j < resource; j++) {
                    System.out.print(allocation[i][j]+" ");
                }
                System.out.print("\t\t\t\t");
                for (int j = 0; j < resource; j++) {
                    work[j] = work[j] + allocation[i][j];
                    System.out.print(work[j]+" ");
                }
                System.out.print("\t\t\t\t");
                System.out.println(F[i]);
            }
            /**
             * 如果循环一遍没有任何的线程被分配资源,那么这个线程是不安全的
             */
            if (i == thread - 1 && count == count1) {
                System.out.println("该线程不安全");
                return false;
            }
            /**
             * 从头再继续循环
             */
            if (count < thread && i == thread - 1) {
               // System.out.println("count < thread && i == thread - 1");
                count1 = count;
                i = -1;
            }
            if (count == thread) {
                System.out.print("该线程的安全序列为:");
                for (int j = 0; j < thread; j++) {
                    System.out.print(way[j]+"  ");
                }
                System.out.println();
                return true;
            }
        }
        return false;
    }

    public boolean update(int p,int[] request){
        for(int i = 0;i < resource;i++){
            if(request[i] > need[p][i]){
                System.out.println("线程不安全");
                return false;
            }
            if(request[i] > avilable[i]){
                System.out.println("线程不安全");
                return false;
            }
        }
         return true;
    }


    /**
     * 预分配
     */
    public void preAll(){
        boolean b = true;
        // 预分配资源
        System.out.print("请选择进程申请资源: p");
        int p = scanner.nextInt();
        int[] request = new int[resource];
        System.out.print("申请资源数:");
        request = inputone(resource);//需要请求的资源
        int[] work1 = avilable.clone();
        int [][] all = allocation.clone();
        int n[][] = need.clone();
        int[] work2 = avilable.clone();
        /**
         * 输入合法
         */
        if(update(p,request) == true){
            //预分配
            for(int i = 0;i < resource;i++){
                work1[i] = work1[i] - request[i];
                all[p][i] = all[p][i] + request[i];
                n[p][i] =  n[p][i] - request[i];
                if(n[p][i] != 0){//数据不为0
                    b = false;
                }
            }
            if(b == true){//进程可以运行完毕
                for(int i = 0;i < resource;i++){
                    work1[i] = all[p][i]+work1[i];
                    all[p][i] = 0;
                }
            }
        }


        work2 = work1.clone();
        //public boolean safe(int[] work,int[][] allocation,int[][] need){
        if(safe(work2,all,n)){//安全性检查
           //线程安全2
            avilable= work1.clone();
            allocation = all;
            need = n;
        }
        show();
    }

    public void menu(){
        while(true){
            System.out.print("是否预分配(Y/N):");
            char ch = scanner.next().charAt(0);
            switch (ch){
                case 'Y':
                    preAll();//预分配
                    break;
                case 'N':
                    System.out.println("退出系统");
                    System.exit(0);
                    break;
                default:
                    System.out.print("输入不合法,重新输入:");
                    break;
            }
        }
    }
    public static void main(String[] args) {
        BankerAlgorithm banker = new BankerAlgorithm();
        banker.init();
        banker.menu();
    }
 }

运行结果:
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值