zoukankan      html  css  js  c++  java
  • 操作系统——银行家算法(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++;
            }
    
        }

    测试用例:

     

     申请资源:

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

     

         

  • 相关阅读:
    用户 'IIS APPPOOLPrivate' 登录失败。
    WCF 内置跟踪日志
    Ionic3 下拉刷新
    Ionic3 组件懒加载
    Ionic3 编程-应用启动进入引导页
    mysql数据库导入导出
    PHP-生成二维码(qr-code)
    javascript 总结(常用工具类的封装)
    Ajax跨域原理及解决方案
    封装获取连续数字的拼接
  • 原文地址:https://www.cnblogs.com/128-cdy/p/12188340.html
Copyright © 2011-2022 走看看