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

Posted 蔡小菜i

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作系统——银行家算法(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++;
        }

    }

 

测试用例:

 

 

 申请资源:

 

 

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

 

 

     

以上是关于操作系统——银行家算法(java实现)的主要内容,如果未能解决你的问题,请参考以下文章

怎么处理JAVA多线程死锁问题?

计算机操作系统 --- 共享资源分配与银行家算法java篇

计算机操作系统 --- 共享资源分配与银行家算法java篇

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

OS学习笔记死锁总结(含银行家算法的实现Java版)

关于银行家算法中部分代码不理解,请高手帮忙指点下谢谢!!!