首页 > 编程语言 > 详细

银行家算法

时间:2020-03-21 18:43:05      阅读:54      评论:0      收藏:0      [点我收藏+]

在银行家算法中,发现这样一个问题:在网上的大多数代码资料中,进程的已分配资源是手动输入的,其目的是保证系统可用资源能使至少一个进程执行,但在实际操作中,对系统而言,在用户的操作下,进程的资源需求可以看作是随机的。若是系统的资源无法满足任意一个进程执行,那么将产生死锁,这样的情况应该是少见的。针对这样一个问题,在此算法基础之上,做出假设。当系统的资源无法满足任意一个进程执行时。根据对银行家算法的理解,银行家算法前提是以一个进程的资源释放为基础,采用释放掉某个进程已拥有资源的策略。不难想象,在当系统发现一个进程都无法执行时,可以释放一个进程或多个进程已拥有的资源,可以看作是系统剥夺进程的资源,可以再进行银行家算法,实现安全状态

在操作系统中还有一种鸵鸟算法,就是忽视问题。鸵鸟算法可以看作解决该问题的解决方式的一个极限。这种解决问题的方式可以看作实在逃避问题(逃避虽可耻但有用),逃避的目的积累能量,在找到突破口后,利用银行家算法滚雪球的优势解决问题(集中力量办大事,面对困难奥利给)。

程序(JAVA)实现上,当系统的资源无法满足任意一个进程执行时,采用随机的释放掉一个进程的方式,直到可以执行一个程序为止。可以说这是一种简单的策略,当然还可以考虑更多的条件,比如该释放哪一个进程(按优先级或是按进程已占资源的多少),释放进程的哪一类资源(内存、显存…)。我采用的是随机选择的方式。这种的方式实现简单,而且此时的系统资源本来就很紧张了。在解决这种少见问题的方式上,可以类比于用户打开windows操作系统上的任务管理器结束进程,当然更极端的方式是长按电源键,实现重启,也算是鸵鸟式操作。代码如下

进程对象:

import java.util.Random;

/*
 * author@ 蒋龙荣 2020-03-19
 * 
 * Proceeding 类 将进程看作对象
 * 属性:
 * 进程所需最大 A B C 资源 , @A_MaxRequire,@B_MaxRequire,@C_MaxRequire
 * 已分配资源  @A_AlreadyGet,@B_AlreadyGet,@C_AlreadyGet
 * 进程还需要的资源 @A_Need,@B_Need,@C_Need
 * 进程状态 @Status
 * 进程ID @ProcessingID
 */
public class Process {
    // 进程需要的A、B、C类最大资源
    int A_MaxRequire;
    int B_MaxRequire;
    int C_MaxRequire;

    // 进程已经分配到的A、B、C类资源
    int A_AlreadyGet;
    int B_AlreadyGet;
    int C_AlreadyGet;

    // 进程还需要的A、B、C类资源
    private int A_Need;
    private int B_Need;
    private int C_Need;

    // 进程的状态 Wating(等待),Keilled(结束)
    String Status = "Waiting";
    
    //进程本身的ID
    public int ProcessID ;

    Random random = new Random();

    public Process(int a_maxRequire, int b_maxRequire, int c_maxRequire, 
            int a_alreadyGet, int b_alreadyGet,int c_alreadyGet,
            int proceedingID) {
        this.A_MaxRequire = a_maxRequire;
        this.B_MaxRequire = b_maxRequire;
        this.C_MaxRequire = c_maxRequire;
        this.A_AlreadyGet = a_alreadyGet;
        this.B_AlreadyGet = b_alreadyGet;
        this.C_AlreadyGet = c_alreadyGet;
        this.ProcessID = proceedingID;
        this.ProcessNeed();
        this.JudgeStatus();
        this.toString();
    }

    public Process() {

    }

    // 随机生成进程所需的最大资源
    public void GenerateMaxRequire() {
        A_MaxRequire = random.nextInt(14); // waiting for change
        B_MaxRequire = random.nextInt(8);
        C_MaxRequire = random.nextInt(7);
    }

    // 在不超过当前资源最大值情况下随机生成已获得的资源
    public void GenerateAlreadyGet(Process lastProcess) {
        Source.A_Source = Source.A_Source - lastProcess.A_AlreadyGet;
        A_AlreadyGet = random.nextInt(Source.A_Source); 

        Source.B_Source = Source.B_Source - lastProcess.B_AlreadyGet;
        B_AlreadyGet = random.nextInt(Source.B_Source);

        Source.C_Source = Source.C_Source - lastProcess.C_AlreadyGet;
        C_AlreadyGet = random.nextInt(Source.C_Source);

    }

    // 计算需要的资源
    public void ProcessNeed() {
        A_Need = A_MaxRequire - A_AlreadyGet; // waiting for change
        B_Need = B_MaxRequire - B_AlreadyGet;
        C_Need = C_MaxRequire - C_AlreadyGet;
    }

    // 判断进程状态 waiting 或 killed
    public void JudgeStatus() {
        if (A_MaxRequire > A_AlreadyGet || B_MaxRequire > B_AlreadyGet || C_MaxRequire > C_AlreadyGet)
            Status = "Waiting";
        else
            Status = "Killed";
    }

    // 释放该进程的资源(在未找到安全的序列时)
    public void ReleaseSource() {
        Source.A_Source = Source.A_Source + this.A_AlreadyGet;
        Source.B_Source = Source.B_Source + this.B_AlreadyGet;
        Source.C_Source = Source.C_Source + this.C_AlreadyGet;
        this.A_AlreadyGet = 0;
        this.B_AlreadyGet = 0;
        this.C_AlreadyGet = 0;
        
    }

    @Override
    public String toString() {
        return "\nA_MaxRequire=" + A_MaxRequire + ", B_MaxRequire=" + B_MaxRequire + ", C_MaxRequire="
                + C_MaxRequire + ", \nA_AlreadyGet=" + A_AlreadyGet + ", B_AlreadyGet=" + B_AlreadyGet
                + ", C_AlreadyGet=" + C_AlreadyGet + ", \nA_Need=" + A_Need + ", \tB_Need=" + B_Need + ", \tC_Need="
                + C_Need + ", \nStatus=" + Status +"\t"+"ProcessID:   "+ProcessID+ "\n\n";
    }
 

资源对象:

   public  class Source {
    //各种资源的情况
    public   static int A_Source = 15;
    public   static int B_Source = 12;
    public   static int C_Source = 9;
    

    public static String ToString() {
        return "Source [A_Source=" + A_Source + ", B_Source=" + B_Source + ", C_Source=" + C_Source + "]\n";
    }
    
    
   }

算法部分:

/*
 * author @ 蒋龙荣 170404121 2020-03-20
 * 软件技术基础作业
 * 进程组@test.Process
 * 待排序的进程组容器@CompareSequence,用于等待排好序的进程
 * 已排好序的进程组的容器@ProcessSequence,用于容纳已经排好序的进程
 */
import java.util.Objects;
import java.util.Random;

public class test {
    // 假设有 5 个进程
    static Process[] Process = new Process[5];
    // 已排好序的进程组的容器 
    static Process[] ProcessSequence = new Process[5];
    // 待排序的进程组容器
    static Process[] CompareSequence = new Process[5];
    //资源对象
    static Source source = new Source();
    

    public static void Initialize() {
        //初始化  进程组@test.Process,待排序的进程组容器@CompareSequence,已排好序的进程组的容器@ProcessSequence ,一共 5 个进程
        test.Process[0] = new Process(5, 6, 3, 1, 2, 1, 0);//初始化第 0 个
        CompareSequence[0] = new Process(0, 0, 0, 0, 0, 0, -1);
        ProcessSequence[0] = new Process(0, 0, 0, 0, 0, 0, -2);
        System.out.print("Proceeding_0" + test.Process[0].toString());
        //从 第 1 个开始初始化
        for (int i = 1; i < 5; i++) {
            // Took me long time find the nullpointer bug
            // Initialize the objects first!!!!!!!
            test.Process[i] = new Process();
            // 生成进程 ID
            test.Process[i].ProcessID = i;
            // 生成所需进程最大的资源需求
            test.Process[i].GenerateMaxRequire();
            // 生成进程已经得到的资源
            test.Process[i].GenerateAlreadyGet(test.Process[i - 1]); // 根据上一个进程随机分配资源
            // 计算进程所需的资源 MaxRequire - AlreadyGet
            test.Process[i].ProcessNeed();
            // 判断进程的状态
            test.Process[i].JudgeStatus();

            System.out.print("Process_" + i + test.Process[i].toString());

            CompareSequence[i] = new Process(0, 0, 0, 0, 0, 0, -1);
            ProcessSequence[i] = new Process(0, 0, 0, 0, 0, 0, -2);
        }
        //计算最后剩下的资源
        Source.A_Source = Source.A_Source - test.Process[4].A_AlreadyGet;
        Source.B_Source = Source.B_Source - test.Process[4].B_AlreadyGet;
        Source.C_Source = Source.C_Source - test.Process[4].C_AlreadyGet;
        System.out.print("After ini tializing,the left Source: "+Source.ToString());

    }

    public static void main(String[] args) {
        Random ran = new Random();
        // 待排序的进程组容器的序号
        int j = 0;
        // 已排好序进程组容器的序号
        int k = 0;
        //初始化
        test.Initialize();
        // 第一次排序,用于检查一开始可以执行的进程
        for (int i = 0; i < 5; i++) {
            //判断进程预分配的资源是否满足运行要求
            if (Objects.equals("Killed", Process[i].Status)) {
                // 预分配的资源满足运行要求,释放该进程资源
                Process[i].ReleaseSource();
                // 装入已排好序进程组容器
                ProcessSequence[k] = Process[i];
                //序号加 1
                k++;
            } else
            // 将进程转入待进程组容器,等待分配资源
            {
                CompareSequence[j] = Process[i];
                //序号加一
                j++;
            }
        }
        // 有 j 次循环, j 表示待排序的进程数
        again: for (int i = 0; i < j; i++) {
            // 在初始分配时就满足所有进程所需资源
            if (j == 0)
                // 跳出循环
                break;
            // 尝试分配资源给进程
            else if (((CompareSequence[i].A_AlreadyGet + Source.A_Source) >= CompareSequence[i].A_MaxRequire)
                    && ((CompareSequence[i].B_AlreadyGet + Source.B_Source) >= CompareSequence[i].B_MaxRequire)
                    && ((CompareSequence[i].C_AlreadyGet + Source.C_Source) >= CompareSequence[i].C_MaxRequire)) { // 释放内存
                CompareSequence[i].ReleaseSource();
                // 将进程装入执行进程组
                ProcessSequence[k] = CompareSequence[i];
                // 执行进程组的个数加 1
                k++;
                // 待比较的进程组个数减 1
                j--;
                // 将待比较的进程序列从 i 处开始,向前移一位
                for (int m = i; m < 4; m++)
                    CompareSequence[m] = CompareSequence[m + 1];
                i = -1;
                continue again;
                //无法找到一个可以进行的进程
            } else if (i == j - 1) {
                //产生随机数,随机指定待排序的进程组中的一个进程释放资源
                int num = ran.nextInt(5);
                //释放资源
                CompareSequence[num].ReleaseSource();
                System.out.print(
                        "Have relased the process,the process ID is " + CompareSequence[num].ProcessID + "\n");
                //初始化循环
                i = -1;
                //跳至循环开头,从新开始循环,从待排序的
                continue again;
            } 
            //找到一个可以进行的进程或是未完判断此次待排序的进程组,继续循环
                continue;

        }

        // 输出排序好后的进程 ID
        System.out.print("The execution sequence of the process ID:\n ");
        for (int i = 0; i < 5; i++) {
            System.out.print(ProcessSequence[i].ProcessID + "\t");
        }

    }
}

运行结果:

技术分享图片

 

 

在此次运行的过程中,出现了在不释放进程已获资源的情况下,无法执行进程的情况,同时在随机释放进程已获资源的情况的策略中,出现多次释放同一进程的情况,导致释放资源无效,进而再次随机释放进程资源,出现无效释放的情况,这种情况也许比较少见,也是设计的一个缺陷。

银行家算法

原文:https://www.cnblogs.com/jianglongrong/p/12540618.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!