实验(二)银行家算法模拟

一、实验名称

实验(二)银行家算法模拟

二、实验目的

通过银行家算法的模拟,加深理解操作系统中死锁的概念,掌握死锁产生的原因、必要条件以及解决死锁的方法。

三、实验内容和要求

利用程序设计语言定义银行家算法中所需的数据结构:
可利用资源向量Available;
最大需求矩阵Max;
分配矩阵Allocation;
需求矩阵Need;
假定系统中有五个进程{P0,P1,P2,P3,P4}和三类资源{A,B,C},各类资源的数量分别为10、5、7,在T0时刻的资源分配情况如下表:
Max
A B C Allocation
A B C Need
A B C Available
A B C
P0 7 5 3 0 1 0 7 4 3 3 3 2
P1 3 2 2 2 0 0 1 2 2
P2 9 0 2 3 0 2 6 0 0
P3 2 2 2 2 1 1 0 1 1
P4 4 3 3 0 0 2 4 3 1
利用安全性算法分析T0时刻的安全性。
P1发出请求向量Request(1,0,2),模拟系统按银行家算法进行检查;
P4发出请求向量Request(3,3,0),模拟系统按银行家算法进行检查;
P0发出请求向量Request(0,2,0),模拟系统按银行家算法进行检查;

四、实验设计

1、实验内容

实验环境:jdk1.8
程序代码:


package com.symc.dsaa.os.test2;
import java.util.LinkedList;
/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/11/17 10:42
 * @Description: 将进程封装
 */
public class Process {
    /**
     * 定义各种变量,定义的名称意思很清晰
     * 如,maxA就是A类资源的最大量
     * 将资源实例化,用集合存放起来ArrayList在这里不好用
     * 一个资源就占一个单位空间,这是已分配的,已存在的,所以我用对象来代替
     * max和need是不存在的,给个数字描述一下
     */
    private String name;
    private int maxA;
    private LinkedList<ResourceA> allocationA = new LinkedList<>();
    private int needA;
    private int maxB;
    private LinkedList<ResourceB> allocationB = new LinkedList<>();
    private int needB;
    private int maxC;
    private LinkedList<ResourceC> allocationC = new LinkedList<>();
    private int needC;
    /**
     * 创建和初始化进程
     * 这里创建一个对象,命名,一切变量都通过方法封装好了,在这里调用
     * 具体解释在下面有介绍
     * @param num 用来定义进程名
     * @param maxes 存放的最大资源的数组
     * @param allocations 存放需求资源的数组
     * @return 最后返回一个Process对象,方便快速创建进程
     */
    public static Process createAndInitProcess(int num, int[] maxes, int[] allocations) {
        Process process = new Process();
        process.setName(num);
        process.setAllMax(maxes[0], maxes[1], maxes[2]);
        process.setAllAllocation(allocations[0], allocations[1], allocations[2]);
        process.AutoSetAllNeed();
        return process;
    }
    /**
     * 发起资源请求,是由进程发起的请求,所以封装在Process类中
     * 请求时将available中的资源取出,放到allocation中
     * @param amount 假如一开始请求abc分别为(1,0,2),这个存在amount中
     * @param availableResourcesA
     * @param availableResourcesB
     * @param availableResourcesC
     */
    public void request(int[] amount, LinkedList<ResourceA> availableResourcesA,
 LinkedList<ResourceB> availableResourcesB,
 LinkedList<ResourceC> availableResourcesC) {
        for (int i = 0; i < amount[0]; i++) {
 allocationA.addLast(availableResourcesA.removeLast());
        }
        for (int i = 0; i < amount[1]; i++) {    allocationB.addLast(availableResourcesB.removeLast());
        }
        for (int i = 0; i < amount[2]; i++) {    allocationC.addLast(availableResourcesC.removeLast());        }    }
    /**
     * 归还资源
     * 当此进程成功执行结束了,它所占用的所有资源即Max中应全部归还到Available中
     * @param availableResourcesA
     * @param availableResourcesB
     * @param availableResourcesC
     */
    public void returnResources(LinkedList<ResourceA> availableResourcesA,LinkedList<ResourceB> availableResourcesB,LinkedList<ResourceC> availableResourcesC) {
        for (int i = 0; i < allocationA.size(); i++) {            availableResourcesA.addLast(allocationA.removeLast());        }
        for (int i = 0; i < allocationB.size(); i++) {            availableResourcesB.addLast(allocationB.removeLast());        }
        for (int i = 0; i < allocationC.size(); i++) {           availableResourcesC.addLast(allocationC.removeLast());       }
    }
    /**
     * 初始化进程的max
     * @param maxA
     * @param maxB
     * @param maxC
     */
    public void setAllMax(int maxA, int maxB, int maxC) {
        this.maxA = maxA;
        this.maxB = maxB;
        this.maxC = maxC;
    }
    /**
     * 初始化进程的allocation
     * @param allocationA
     * @param allocationB
     * @param allocationC
     */
    public void setAllAllocation(int allocationA, int allocationB, int allocationC) {
        for (int i = 0; i < allocationA; i++) {
            this.allocationA.addLast(new ResourceA());
        }
        for (int i = 0; i < allocationB; i++) {
            this.allocationB.addLast(new ResourceB());
        }
        for (int i = 0; i < allocationC; i++) {
            this.allocationC.addLast(new ResourceC());
        }
    }
    /**
     * 自动计算need,max=allocation+need
     */
    public void AutoSetAllNeed() {
        this.needA = maxA - allocationA.size();
        this.needB = maxB - allocationB.size();
        this.needC = maxC - allocationC.size();
    }
    public String getName() {
        return name;
    }
    public void setName(int num) {
        this.name = "P" + num;
    }
    public int getNeedA() {
        return needA;
    }
    public int getNeedB() {
        return needB;
    }
    public int getNeedC() {
        return needC;
    }
}
package com.symc.dsaa.os.test2;

import java.util.LinkedList;
/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/11/17 10:39
 * @Description: 银行家算法模拟
 */
public class BankerAlgorithmSimulation {

    /**
     * 创建用于存放available资源的集合
     */
    public static LinkedList<ResourceA> availableResourcesA =
            new LinkedList<ResourceA>();
    public static LinkedList<ResourceB> availableResourcesB =
            new LinkedList<ResourceB>();
    public static LinkedList<ResourceC> availableResourcesC =
            new LinkedList<ResourceC>();
    /**
     * InitAvailableResources:初始化可获得资源;
     * int[][] maxes、int[][] allocations:存入题中数据
     * int requestAmount[]:定义请求资源,并且可以多次请求
     * 测试序列并打印结果
     * @param args
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws ClassNotFoundException {
        BankerAlgorithmSimulation bas = new BankerAlgorithmSimulation();
        bas.InitAvailableResources(3, 3, 2);
        int[][] maxes = {
                {7, 5, 3},
                {3, 2, 2},
                {9, 0, 2},
                {2, 2, 2},
                {4, 3, 3}
        };
        int[][] allocations = {
                {0, 1, 0},
                {2, 0, 0},
                {3, 0, 2},
                {2, 1, 1},
                {0, 0, 2}
        };
        Process p0 = Process.createAndInitProcess(0, maxes[0], allocations[0]);
        Process p1 = Process.createAndInitProcess(1, maxes[1], allocations[1]);
        Process p2 = Process.createAndInitProcess(2, maxes[2], allocations[2]);
        Process p3 = Process.createAndInitProcess(3, maxes[3], allocations[3]);
        Process p4 = Process.createAndInitProcess(4, maxes[4], allocations[4]);
        int requestAmount[] = {1, 0, 2};
        LinkedList<Process> processes = new LinkedList<>();
        processes.add(p0);
        processes.add(p1);
        processes.add(p2);
        processes.add(p3);
        processes.add(p4);
        if (bas.canRequest(requestAmount)) {
            p1.request(requestAmount, availableResourcesA,
                    availableResourcesB, availableResourcesC);
//            System.out.print(p1.getName());
            if (p1.getNeedA() == 0 && p1.getNeedB() == 0 && p1.getNeedC() == 0) {
                p1.returnResources(availableResourcesA, availableResourcesB,availableResourcesC);
            }
            while (processes.size()>0){
                bas.runProcess(processes.remove());
            }
        } else {
            System.out.println("不安全!");
        }
    }
    /**
     * 通过available和need资源的比较
     * 判断传入的进程是否可以直接执行完,若可以,就返回true,同时输出当前进程
     * 用于后面循环判断进程是否安全
     * @param p
     * @return
     */
    public boolean runProcess(Process p) {
        if (availableResourcesA.size() >= p.getNeedA() &&availableResourcesB.size() >= p.getNeedB() &&
availableResourcesC.size() >= p.getNeedC()) {
System.out.print("->" + p.getName());
            p.returnResources(availableResourcesA,availableResourcesB,availableResourcesC);
            return true;
        }else {
            return false;
        }
    }
    /**
     * 判断是否能发出请求,如果连发出请求的资源都满足不了,那当前绝对不会是安全的。
     * @param requestAmount
     * @return
     */
    public boolean canRequest(int[] requestAmount) {
        if (requestAmount[0] > availableResourcesA.size() ||
                requestAmount[1] > availableResourcesB.size() ||
                requestAmount[2] > availableResourcesC.size()) {
            return false;
        }
        return true;
    }

    /**
     * 初始化可获得资源,available堆中中也是实体的资源,应当创建Resource对象
     * @param amountA
     * @param amountB
     * @param amountC
     */
    public void InitAvailableResources(int amountA, int amountB, int amountC) {
        for (int i = 0; i < amountA; i++) {
            availableResourcesA.add(new ResourceA());
        }
        for (int i = 0; i < amountB; i++) {
            availableResourcesB.add(new ResourceB());
        }
        for (int i = 0; i < amountC; i++) {
            availableResourcesC.add(new ResourceC());
        }
    }
}

package com.symc.dsaa.os.test2;
/**
 * @Author: 凤文  沈阳医学院2019级医学信息工程 0213
 * @CreateTime: 2021/11/17 10:42
 * @Description: 创建资源类,A、B、C三类资源都继承这个类
 */
public class Resource {
    protected String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public class ResourceA extends Resource {
    private String name = "A";
}
public class ResourceB extends Resource{
    private String name = "B";
}
public class ResourceC extends Resource{
    private String name = "C";
}

2、实验结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、实验中出现的问题及解决方法

问题1:请求资源时的算法

进程添加一个LinkedList用来存放allocation的资源,可用资源堆用来存放available的资源,当发起请求时,available移除的资源添加到allocation中。
实现算法:
for (int i = 0; i < amount[0]; i++) {
allocationA.addLast(availableResourcesA.removeLast());
}

问题2:归还资源

当进程使用资源结束,应当将自身的allocation或者说max资源释放到available中。这个算法的实现刚好跟问题1的过程时相反的:
for (int i = 0; i < allocationA.size(); i++) {
availableResourcesA.addLast(allocationA.removeLast());
}

七、结论

max=allocation+need。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
实验目的】 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
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值