银行家算法

 银行家算法模拟
我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.
银行家算法数据结构
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]

算法 的实现
一、初始化
由用户输入数据,分别对可利用资源向量矩阵AVAILABLE 、 最大需求矩阵MAX 、分配矩阵ALLOCATION、 需求矩阵NEED 赋值。
二、银行家算法
在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。
银行家算法的基本思想是分配资源之前, 判断系统是否是安全的; 若是, 才分配。它是最具有 代表性的避免死锁的算法。
设进程cusneed 提出请求REQUEST [i] ,则银行家算法按如下规则进行判断。
(1) 如果REQUEST [cusneed] [i]<= NEED[cusneed][i] ,则转(2) ;否则,出错。
(2) 如果REQUEST [cusneed] [i]<= AVAILABLE[cusneed][i] ,则转(3) ;否则,出错。
(3) 系统试探分配资源,修改相关数据:
AVAILABLE[i]-=REQUEST[cusneed][i];
ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];
NEED[cusneed][i]-=REQUEST[cusneed][i];
(4) 系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复 原状, 进程等待。
三、安全性检查算法
(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,则系统处于安全状态。安全状态一定是没有死锁发生。
不存在一个安全序列。不安全状态不一定导致死锁。

各算法流程图
初始化算法流程图:

银行家算法流程图:

安全性算法流程 图:

package Banker;

import java.util.Scanner;

public class Banker {

    /**
     * @param args
     */

     int MAXPROCESS =50;                        /*最大进程数*/  
    int  MAXRESOURCE =100;                        /*最大资源数*/  

    int m,n;                                    /*m个进程,n个资源*/  

     int[][] MAX;
        int[][] ALLOCATION ;
        int[][] NEED ;
        int[] AVAILABLE ;
        int[][] REQUEST ;
        int[]  p ;
      boolean[]  FINISH ;
    public void Init()                /*初始化算法*/  
    {  
        int i,j; 
        Scanner in = new Scanner(System.in);
        System.out.println("请输入进程的数目:");  
         m=in.nextInt();
        System.out.println("请输入资源的种类:");  
         n=in.nextInt();  
        System.out.println("请输入每个进程最多所需的各资源数,按照"+m+"x"+n+"矩 阵输入");  
     MAX   =new int[m][n];
        for(i=0;i<m;i++) { 
            for(j=0;j<n;j++)  {
                 MAX[i][j]=in.nextInt();  
            }}
        System.out.println("请输入每个进程已分配的各资源数,也按照"+m+"x"+n+"矩 阵输入"); 

        ALLOCATION=new int[m][n];

         NEED=new int[m][n];
         AVAILABLE=new int[n];
         REQUEST=new int[m][n];
         p=new int[m];
      FINISH=new boolean[m];
        for(i=0;i<m;i++)  
        {  
            for(j=0;j<n;j++)  
            {  
                ALLOCATION[i][j]=in.nextInt();  
                NEED[i][j]=MAX[i][j]-ALLOCATION[i][j];  
                if(NEED[i][j]<0)  
                {  
                    System.out.println("您输入的第"+i+1+"个进程所拥有的第"+j+1+"个资源数 错误,请重新输入:");  
                    j--;  
                    continue;  
                }  
            }  
        }  
        System.out.println("请输入各个资源现有的数目:");  

        for(i=0;i<n;i++)  
        {  
           AVAILABLE[i]=in.nextInt();  
        }  
    }  
    void Bank()                /*银行家算法*/  
    {  

         Scanner in = new Scanner(System.in);
         int i,cusneed,flag = 0;  
        char again;  
        while(true)  
        {  
            showdata(n,m);////////////////////////////////////////////////////////////////////  


        System.out.println("请输入要申请资源的进程号(注:第1个进程号为0,依次类推)");  
        int cusneed1=in.nextInt();  
            if (cusneed1 > m)  
            {  
                System.out.println("没有该进程,请重新输入");  

            }  
            System.out.println("请输入进程所请求的各资源的数量");  
            for(i=0;i<n;i++)  
            {  
             REQUEST[cusneed1][i]=in.nextInt();  
            }  
            for(i=0;i<n;i++)  
            {  
                if(REQUEST[cusneed1][i]>NEED[cusneed1][i])//如果用户选择的线程的第i个资源请求数>该线程该资源所需的数量  
                {  
                    System.out.println("您输入的请求数超过进程的需求量!请重新输入!");  

                }  
                if(REQUEST[cusneed1][i]>AVAILABLE[i])//如果用户选择的线程的第i个资源请求数>系统现有的第i个资源的数量  
                {  
                    System.out.println("您输入的请求数超过系统有的资源数!请重新输入!");  

                }  
            }  
            for(i=0;i<n;i++)//如果请求合理,那么下面  
            {  
                AVAILABLE[i]-=REQUEST[cusneed1][i];//系统可用资源减去申请了的  
                ALLOCATION[cusneed1][i]+=REQUEST[cusneed1][i];//线程被分配的资源加上已申请了的  
                NEED[cusneed1][i]-=REQUEST[cusneed1][i];//线程还需要的资源减去已申请得到的  
            }  
            if(Safe())//AVAILABLE  ALLOCATION  NEED变动之后,是否会导致不安全  
            {  
                System.out.println("同意分配请求!");  
            }  
            else  
            {  
                System.out.println("您的请求被拒绝!");  
                for(i=0;i<n;i++)  
                {  
                    AVAILABLE[i]+=REQUEST[cusneed1][i];  
                    ALLOCATION[cusneed1][i]-=REQUEST[cusneed1][i];  
                    NEED[cusneed1][i]+=REQUEST[cusneed1][i];  
                }  
            }  
            for (i=0;i<n;i++)  
            {  
                if (NEED[cusneed1][i] <= 0)  
                {  
                    flag++;  
                }  
            }  
            if (flag == n)//如果该进程各资源都已满足条件,则释放资源  
            {  
                for (i=0;i<n;i++)  
                {  
                    AVAILABLE[i] += ALLOCATION[cusneed1][i];  
                    ALLOCATION[cusneed1][i] = 0;  
                    NEED[cusneed1][i] = 0;  
                }  
                System.out.println("线程"+cusneed1+" 占有的资源被释放!");  
                flag = 0;  
            }  
            for(i=0;i<m;i++)//分配好了以后将进程的标识FINISH改成false  
            {  
                FINISH[i]=false;  
            }  
            System.out.println("您还想再次请求分配吗?是请按y/Y,否请按其它键");  
           again=(char) in.nextInt();  
            if(again=='y'||again=='Y')  
            {  
                continue;  
            }  
            break;  
        }  
    }  
     public Boolean Safe()                                    /*安全性算法*/  
    {  
        int i,j,k,l=0;  
        int[] Work =new int[MAXRESOURCE];                    /*工作数组*/  
        for(i=0;i<n;i++)  
            Work[i]=AVAILABLE[i];  
        for(i=0;i<m;i++)  
        {  
            FINISH[i]=false;//FINISH记录每个进程是否安全  
        }  
        for(i=0;i<m;i++)  
        {     
            for(j=0;j<n;j++)//循环查找第i个进程需要的各个资源数 是否 超过系统现有的对应的资源数  
            {  
                if(NEED[i][j]>Work[j])//第i个进程需要的第j个资源数 > 系统现有的第j个资源数  
                {  
                    break;  
                }  
            }  
            if(j==n)//如果第i个进程所需的各个资源数都没有超过系统现有的对应资源数  
            {   
                FINISH[i]=true;//给该进程的FINISH标记为true  
                for(k=0;k<n;k++)  
                {  
                    Work[k]+=ALLOCATION[i][k];//将Work赋值为 第i个进程各个已分配资源数+系统现有的对应资源数(因为当改进程全部资源数都满足时线程结束并将资源返还给系统)  
                }  
                p[l++]=i;//记录进程号  
            }  
            else//如果超过继续循环下一个进程  
            {  
                continue;   
            }  
            if(l==m)//当所有进程都能够被满足运行时  
            {  
                 System.out.println("系统是安全的");  
                 System.out.println("安全序列:");  
                for(i=0;i<l;i++)//改了146行的i值,显示资源分配给进程的顺序  
                {  
                     System.out.println(p[i]);  
                    if(i!=l-1)  
                    {  
                        System.out.println("-->");  
                    }  
                }  
                System.out.println("");           
                return true;  
            }  
        }//for循环  
        System.out.println("系统是不安全的");  
        return false;  
    }  

    void showdata(int n,int m)   //显示  
    {  
        int i,j;  
        System.out.println();    
        System.out.println("-------------------------------------------------------------");    
        System.out.println("系统可用的资源数为:    ");  
        for   (j=0;j<n;j++)         
            System.out.println("    "+AVAILABLE[j]);        
        System.out.println();     
        System.out.println("各进程还需要的资源量:");   
        for   (i=0;i<m;i++)     
        {  
            System.out.println("    进程"+i+":");     

            for   (j=0;j<n;j++)  
                System.out.println("     "+NEED[i][j]);     

        }     

        System.out.println("各进程已经得到的资源量:    ");     

        for   (i=0;i<m;i++)     
        {  
            System.out.println("    进程"+i+":");     

            for   (j=0;j<n;j++)  
                System.out.println("     "+ALLOCATION[i][j]);  
            System.out.println();     
        }    

    } 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Banker Bank=new Banker();
        Bank.Init();
        Bank.Safe();
        Bank.Bank();
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【实验目的】 1. 理解死锁的概念; 2. 用高级语言编写和调试一个银行家算法程序,以加深对死锁的理解。 【实验准备】 1. 产生死锁的原因  竞争资源引起的死锁  进程推进顺序不当引起死锁 2.产生死锁的必要条件  互斥条件  请求和保持条件  不剥夺条件  环路等待条件 3.处理死锁的基本方法  预防死锁  避免死锁  检测死锁  解除死锁 【实验内容】 1. 实验原理 银行家算法是从当前状态出发,逐个按安全序列检查各客户中谁能完成其工作,然后假定其完成工作且归还全部贷款,再进而检查下一个能完成工作的客户。如果所有客户都能完成工作,则找到一个安全序列,银行家才是安全的。与预防死锁的几种方法相比较,限制条件少,资源利用程度提高了。缺点:该算法要求客户数保持固定不变,这在多道程序系统中是难以做到的;该算法保证所有客户在有限的时间内得到满足,但实时客户要求快速响应,所以要考虑这个因素;由于要寻找一个安全序列,实际上增加了系统的开销.Banker algorithm 最重要的一点是:保证操作系统安全状态!这也是操作系统判断是否分配给一个进程资源的标准!那什么是安全状态?举个小例子,进程P 需要申请8个资源(假设都是一样的),已经申请了5个资源,还差3个资源。若这个时候操作系统还剩下2个资源。很显然,这个时候操作系统无论如何都不能再分配资源给进程P了,因为即使全部给了他也不够,还很可能会造成死锁。若这个时候操作系统还有3个资源,无论P这一次申请几个资源,操作系统都可以满足他,因为操作系统可以保证P不死锁,只要他不把剩余的资源分配给别人,进程P就一定能顺利完成任务。 2.实验题目 设计五个进程{P0,P1,P2,P3,P4}共享三类资源{A,B,C}的系统,{A,B,C}的资源数量分别为10,5,7。进程可动态地申请资源和释放资源,系统按各进程的申请动态地分配资源。要求程序具有显示和打印各进程的某一时刻的资源分配表和安全序列;显示和打印各进程依次要求申请的资源号以及为某进程分配资源后的有关资源数据。 3.算法描述 我们引入了两个向量:Resourse(资源总量)、Available(剩余资源量) 以及两个矩阵:Claim(每个进程的最大需求量)、Allocation(已为每个进程分配的数量)。它们共同构成了任一时刻系统对资源的分配状态。 向量模型: R1 R2 R3 矩阵模型: R1 R2 P1 P2 P3 这里,我们设置另外一个矩阵:各个进程尚需资源量(Need),可以看出 Need = Claim – Allocation(每个进程的最大需求量-剩余资源量) 因此,我们可以这样描述银行家算法: 设Request[i]是进程Pi的请求向量。如果Request[i , j]=k,表示Pi需k个Rj类资源。当Pi发出资源请求后,系统按下述步骤进行检查: (1) if (Request[i]<=Need[i]) goto (2); else error(“over request”); (2) if (Request[i]<=Available[i]) goto (3); else wait(); (3) 系统试探性把要求资源分给Pi(类似回溯算法)。并根据分配修改下面数据结构中的值。 剩余资源量:Available[i] = Available[i] – Request[i] ; 已为每个进程分配的数量: Allocation[i] = Allocation[i] + Request[i]; 各个进程尚需资源量:Need[i] = Need[i]-Request[i]; (4) 系统执行安全性检查,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程以完成此次分配;若不安全,试探方案作废,恢复原资源分配表,让进程Pi等待。 系统所执行的安全性检查算法可描述如下: 设置两个向量:Free、Finish 工作向量Free是一个横向量,表示系统可提供给进程继续运行所需要的各类资源数目,它含有的元素个数等于资源数。执行安全算法开始时,Free = Available .标记向量Finish是一个纵向量,表示进程在此次检查中中是否被满足,使之运行完成,开始时对当前未满足的进程做Finish[i] = false;当有足够资源分配给进程(Need[i]<=Free)时,Finish[i]=true,Pi完成,并释放资源。 (1)从进程集中找一个能满足下述条件的进程Pi ① Finish[i] == false(未定) ② Need[i] D->B->A A 1 6 B 1 5 C 2 4 D 4 7 Available = (2) ; Resourse = (10) ; 测试结果如下 process number:5 resource number:4 resource series:6 3 4 2 assined matrix:p0:3 0 1 1 p1:0 1 0 0 p2:1 1 1 0 p3:1 1 0 1 p4:0 0 0 0 needed matrix: p0:1 1 0 0 p1:0 1 1 2 p2:3 1 0 0 p3:0 0 1 0 p4:2 1 1 0 p3-->p4-->p0-->p2-->p1 p3-->p4-->p0-->p1-->p2 p3-->p0-->p4-->p2-->p1 p3-->p0-->p4-->p1-->p2 p3-->p0-->p2-->p4-->p1 p3-->p0-->p2-->p1-->p4 p3-->p0-->p1-->p4-->p2 p3-->p0-->p1-->p2-->p4 it is safe,and it has 8 solutions
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值