一、实验名称
实验(二)银行家算法模拟
二、实验目的
通过银行家算法的模拟,加深理解操作系统中死锁的概念,掌握死锁产生的原因、必要条件以及解决死锁的方法。
三、实验内容和要求
利用程序设计语言定义银行家算法中所需的数据结构:
可利用资源向量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。