• 操作系统——银行家算法(java实现)


    1.数据结构

    1. 可利用的资源向量Available:一个含有m个元素的数组,其中每一个元素代表一类可利拥的资源数目,其初始值是系统中所配置的该类全部可用资源数目,其数值随该类资源的分配改变而改变。如果Available[j]=K,则表示系统中现有Rj类资源K个。
    2. 最大需求矩阵Max:一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
    3. 分配矩阵Allocation:一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。
    4. 需求矩阵Need:一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个方能完成其任务。

    Need[i,j]=Max[i,j]-Allocation[i,j] 

    2.银行家算法

    在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。

    设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断。

    (1)如果REQUEST [cusneed] [i]<= NEED[cusneed][i],则转(2);否则,出错。

    (2)如果REQUEST [cusneed] [i]<= AVAILABLE[i],则转(3);否则,等待。

    (3)系统试探分配资源,修改相关数据:

    AVAILABLE[i]-=REQUEST[cusneed][i];

    ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];

    NEED[cusneed][i]-=REQUEST[cusneed][i];

    (4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。

    3.安全性算法 

    (1)设置两个工作向量Work=AVAILABLE;FINISH

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

    FINISH==false;

    NEED<=Work;

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

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

    Work=Work+ALLOCATION;

    Finish=true;

    GOTO 2

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

    主要代码:

    安全性检测:

    public void allocation(){
            flag_i.clear();
            for (int i = 0; i < this.processes_Size ; i++) {
                Finish[i] = false;
            }
            for (int i = 0; i < this.Resources_Size ; i++) {
                Work[0][i] = AvailableTmp[0][i];
            }
            int count = 0;
            int flag = 0; //flag_i中的个数
            while (count < this.processes_Size){
                for (int i = 0; i < this.processes_Size ; i++) {
                    if(flag_i.contains(i)){
                        continue;
                    }else {
                        int k = 0;
                        while (k < this.Resources_Size){
                            if(NeedTmp[i][k] <= Work[count][k] && (this.Finish[count]==false)){
                                k++;
                            }else {
                                k = this.Resources_Size+1;
                            }
                        }
                        if(k == this.Resources_Size){
                            flag_i.add(i);
                            flag++;
                            break;   //每次添加一个
                        }
                    }
                }
    
                //
                //每走一遍for循环应该找到一个,才能往下执行
                if((count+1) == flag){
                    for (int i = 0; i < this.Resources_Size; i++) {
                        Work_All[count][i] = Work[count][i] + AllocationTmp[(int) flag_i.get(count)][i];
                    }
                    this.Finish[count] = true;
                    count++;
                    //赋值
                    for (int i = 0; i < this.Resources_Size; i++) {
                        Work[count][i] = Work_All[count - 1][i];
                    }
                }
                else {
                    count++;
                    System.out.println("第"+count+"次安全性检测失败!");
                    break;
                }
                if(Finish[count-1] == false){
                    break;
                }
            }
            //跳出循环如果有进程数个值,说明每个进程都能满足,将试分配的值真实分配
            if(flag_i.size() == this.processes_Size){
                for (int i = 0; i < this.processes_Size; i++) {
                    for (int j = 0; j < this.Resources_Size ; j++) {
                        Allocation[i][j] =AllocationTmp[i][j];
                        Need[i][j] = NeedTmp[i][j];
                    }
                }
                for (int i = 0; i < this.Resources_Size; i++) {
                    Available[0][i] = AvailableTmp[0][i];
                }
                showResult();
                System.out.println("*********************************");
                show();
            }else {
                if(flag_i.size() == 0){
                    System.out.println("不满足任何进程的需求!");
                    System.out.println("无安全序列!");
                    System.out.println("******************************");
                    show();
                }else {
                    System.out.println("无安全序列!");
                    System.out.println("*****************************");
                    show();
                }
    
            }
    
        }

    银行家分配部分:

     private void requset() {
            copy();
            System.out.println("请输入要请求资源的进程号:");
            String name = scanner.next();
            int putInto = -1;    //判断输入的是几号进程
            for (int i = 0; i < this.processes_Size; i++) {
                if (name.equals(processes[i])){
                    putInto = i;
                }
            }
            //如果输入的在进程序列内不存在
            if(putInto == -1){
                System.out.println("非法输入!");
                return;
            }
            System.out.println();
            System.out.println("请输入再次申请的资源大小:");
            int[] num = new int[this.Resources_Size];   //输入的request值
            for (int i = 0; i < this.Resources_Size; i++) {
                num[i] = scanner.nextInt();
            }
            int k = 0;
            for (int i = 0; i < this.Resources_Size; i++) {
                if ((num[i] <= Need[putInto][i]) && (num[i] <= Available[0][i])) {
                    k++;
                } else {
                    if((num[i] > Need[putInto][i])) {
                        System.out.println("申请大于需要的进程!");
                        System.out.println("***************************");
                        show();
                        return;
                    }
                    if(num[i] > Available[0][i]){
                        System.out.println("资源不足!");
                        System.out.println("***************************");
                        show();
                        return;
                    }
    
                }
    
            }
            //跳出说明满足要求尝试分配资源
            if(k == this.Resources_Size){
                for (int j = 0; j < this.Resources_Size; j++) {
                    NeedTmp[putInto][j] = NeedTmp[putInto][j] - num[j];
                    AllocationTmp[putInto][j]  = AllocationTmp[putInto][j] + num[j];
                    AvailableTmp[0][j] = AvailableTmp[0][j] - num[j];
                }
    
            }
                  allocation();
        }

             但是遇到的问题是,当满足银行家算法但是不满足安全性算法时,怎么将银行家预分配的再次还给初始分配前的值,最终采用临时的副本数组,每次安全性算法都是对副本操作,当满足时,才将原数组改变,然后将其输出,当然还有当一个就是一个进程的所需要的资源已经全部得到,此时应该将其删除序列表,并且将其拿到的资源全部还给系统,以便于其他进程的申请。

    删除进程(已经获取到了全部所需要的资源):

     private void resReturn(){
            int count = 0;
            int num = 0;
            while (count < processes_Size) {
                for (int i = 0; i < this.Resources_Size; i++) {
                    if (Need[count][i] == 0){
                        num++;
                    }
                }
                if(num == Resources_Size){
                    for (int i = 0; i < this.Resources_Size ; i++) {
                        Available[0][i] = Allocation[count][i]+Available[0][i];
                    }
    
                    for (int i = 0; i < this.processes_Size; i++) {
                        for (int j = 0; j < this.Resources_Size; j++) {
                            if(i < count){
                                Need[i][j] = Need[i][j];
                                Allocation[i][j] = Allocation[i][j];
                                processes[i] = processes[i];
                            }else {
                            Need[i][j] = Need[i+1][j];
                            Allocation[i][j] = Allocation[i+1][j];
                            processes[i] = processes[i+1];
                            }
                        }
                    }
                    processes_Size--;
                }
                num = 0;
                count++;
            }
    
        }

    测试用例:

     

     申请资源:

    当某个进程所需要的资源全部得到的情况如图:

     

         

  • 相关阅读:
    poj3278 Catch That Cow
    poj2251 Dungeon Master
    poj1321 棋盘问题
    poj3083 Children of the Candy Cor
    jvm基础知识—垃圾回收机制
    jvm基础知识1
    java面试基础必备
    java soket通信总结 bio nio aio的区别和总结
    java scoket aIO 通信
    java scoket Blocking 阻塞IO socket通信四
  • 原文地址:https://www.cnblogs.com/128-cdy/p/12188340.html
Copyright © 2020-2023  润新知