一、实验目的
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。通过编写一个模拟动态资源分配的银行家算法程序,帮助学生进一步深入理解死锁、产生死锁的必要条件、安全状态等重要概念,并掌握避免死锁的具体实施方法。
二、实验内容
3.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]
3.2、银行家算法
设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
(1)如果Requesti[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布最大值。
(2)如果Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,Pi须等待。
(3)系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:
Available[j]=Available[j]-Requesti[j];
Allocation[i,j]=Allocation[i,j]+Requesti[j];
Need[i,j]=Need[i,j]-Requesti[j];
系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
3.3、安全性算法
1)设置两个向量:
工作向量Work: 它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work=Available;
工作向量Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]=false; 当有足够资源分配给进程时, 再令Finish[i]=true。
2)从进程集合中找到一个能满足下述条件的进程:
Finish[i]=false;
Need[i,j]≤Work[j];若找到,执行 (3),否则,执行 (4)
3)当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[j]=Work[i]+Allocation[i,j];
Finish[i]=true;
go to step 2;
4)如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态
三、算法流程图

四、源程序及注释
程序中使用的数据结构和符号说明在原码中有注释。
五、测试数据及运行结果
请规定系统有几种资源
3
第1个资源
输入这个资源的名称
a
输入资源的数量
10
-----这是一个分隔符----
第2个资源
输入这个资源的名称
b
输入资源的数量
5
-----这是一个分隔符----
第3个资源
输入这个资源的名称
c
输入资源的数量
7
-----这是一个分隔符----
系统资源初始化完毕
-----这是一个分隔符----
输入进程的个数
5
第1个进程
输入这个进程的名称
p0
输入这个进程的最大需求的资源MAX
7
5
3
----输入这个进程已经被分配的资源----
0
1
0
第1个进程初始化完毕
第2个进程
输入这个进程的名称
p1
输入这个进程的最大需求的资源MAX
3
2
2
----输入这个进程已经被分配的资源----
2
0
0
第2个进程初始化完毕
第3个进程
输入这个进程的名称
p2
输入这个进程的最大需求的资源MAX
9
0
2
----输入这个进程已经被分配的资源----
3
0
2
第3个进程初始化完毕
第4个进程
输入这个进程的名称
p3
输入这个进程的最大需求的资源MAX
2
2
2
----输入这个进程已经被分配的资源----
2
1
1
第4个进程初始化完毕
第5个进程
输入这个进程的名称
p4
输入这个进程的最大需求的资源MAX
4
3
3
----输入这个进程已经被分配的资源----
0
0
2
第5个进程初始化完毕
p1进程已得到足够资源
此时系统可用资源为:
a有5个资源
b有3个资源
c有2个资源
----这是分割符-----
p3进程已得到足够资源
此时系统可用资源为:
a有7个资源
b有4个资源
c有3个资源
----这是分割符-----
p4进程已得到足够资源
此时系统可用资源为:
a有7个资源
b有4个资源
c有5个资源
----这是分割符-----
p0进程已得到足够资源
此时系统可用资源为:
a有7个资源
b有5个资源
c有5个资源
----这是分割符-----
p2进程已得到足够资源
此时系统可用资源为:
a有10个资源
b有5个资源
c有7个资源
----这是分割符-----
safe
是否需要再次申请资源: 是请输入1 不请输入0
0
Process finished with exit code 0
代码的实现
package 银行家;
//系统资源的数据结构
class Resources {
public String name;
public int num;
public Resources(String name, int num) {
this.name = name;
this.num = num;
}
@Override
public String toString() {
return name + "有" + num + "个资源";
}
}
//进程的数据结构
class PCB {
public String name;
public Resources[] max;//最大需求资源
public Resources[] allocation;//已分配的资源
public Resources[] need;//需要的资源
public boolean finish = false;//表示pcb是否获得足够资源
public PCB(String name, Resources[] max, Resources[] allocation) {
this.name = name;
this.max = max;
this.allocation = allocation;
this.need = new Resources[max.length];
for (int i = 0; i < need.length; i++) {
this.need[i] = new Resources(max[i].name, max[i].num - allocation[i].num);
}
}
@Override
public String toString() {
return this.name +(this.finish ? "进程已得到足够资源" : "需要等待");
}
}
//银行的数据结构
public class bank {
//我们当前所需要的资源
private Resources[] work;
//所有进程
private PCB[] pcbs;
public bank(Resources[] Available, PCB[] pcbs) {
this.work = Available;
this.pcbs = pcbs;
leftOver();
}
//计算可以用剩下可以用的资源
private void leftOver() {
for (int i = 0; i < this.work.length; i++) {
//初始资源减去已分配的资源
this.work[i].num = this.work[i].num - pcbsAllRes(i);
}
}
//计算所有进程已分配的第i个资源总数
private int pcbsAllRes(int index) {
int sum = 0;
for ( PCB p : pcbs
) {
sum += p.allocation[index].num;
}
return sum;
}
//判断是否为安全状态
private boolean ifSafe() {
for (PCB p : pcbs
) {
if (! p.finish) {
return false;
}
}
return true;
}
//进行资源分配
public void resAllocation() {
//对进程进行循环资源分配,当所有进程都需要等待或者所有进程都为安全状态退出循环
for (int i = 0; !ifSafe() && !ifAllNeedWait(); i++) {
//实现循环
if (i == this.pcbs.length) {
i = 0;
}
//判断当前这个进程是否已经获得过足够资源
if (pcbs[i].finish) {
continue;
}
//判断当前这个进程是否需要等待
if (! needWait(pcbs[i])) {
//进行资源分配
mainOperation(pcbs[i]);
System.out.println(pcbs[i]);
System.out.println();
displayWorks();
}
}
System.out.println();
if (ifSafe()) {
System.out.println("safe");
} else {
System.out.println("unsafe");
}
}
private void displayWorks() {
System.out.println("此时系统可用资源为:");
for (Resources r : this.work
) {
System.out.println(r);
}
System.out.println("----这是分割符-----");
}
private boolean ifAllNeedWait() {
for (PCB p : this.pcbs
) {
//如果该进程已经得到了足够的资源就不进行判断
if (!p.finish) {
//如果该进程不需要等待就直接返回false
if (!needWait(p)) {
return false;
}
}
}
return true;
}
private void mainOperation(PCB pcb) {
//运行到这说明该进程可以得到足够的资源,那么直接将该进程已分配的资源放回到系统中
//并将finish改为true
for (int i = 0; i < this.work.length; i++) {
this.work[i].num += pcb.allocation[i].num;
pcb.finish = true;
}
}
private boolean needWait(PCB pcb) {
//挨个判断此时pcb这个进程所需要的每个资源,如果need大于系统当前可分配资源,就说明需要等待
for (int i = 0; i < this.work.length; i++) {
if (this.work[i].num < pcb.need[i].num) {
return true;
}
}
return false;
}
}
//输入的方法运行
package 银行家;
import java.util.Scanner;
public class bankMain {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请规定系统有几种资源");
int num = sc.nextInt();//有几种系统资源 就是 ABCD
//系统总资源
Resources[] av = new Resources[num];
for (int i = 0; i < av.length; i++) {
System.out.println("第" + (i+1) + "个资源");
System.out.println("输入这个资源的名称");
String name = sc.next();
System.out.println("输入资源的数量");
int x = sc.nextInt();
av[i] = new Resources(name, x);//初始化完毕
System.out.println("-----这是一个分隔符----");
}
System.out.println("系统资源初始化完毕");
System.out.println("-----这是一个分隔符----");
System.out.println("输入进程的个数");
int num2 = sc.nextInt();
PCB[] pcbs = new PCB[num2];
for (int i = 0; i < num2; i++) {
System.out.println("第" + (i+1) + "个进程");
System.out.println("输入这个进程的名称"); // 就是 p0 p1 p2那些
String name = sc.next();
System.out.println("输入这个进程的最大需求的资源MAX");
Resources[] max = new Resources[num];
int[] maxNum = new int[num];//几种系统资源就需要给多少种东西
for (int j = 0; j < num; j++) {
maxNum[j] = sc.nextInt();
}
for (int j = 0; j < max.length; j++) {
max[j] = new Resources(av[j].name, maxNum[j]);
}
System.out.println("----输入这个进程已经被分配的资源----");
Resources[] allocation = new Resources[num];
int[] allocationResNum = new int[num];
for (int j = 0; j < num; j++) {
allocationResNum[j] = sc.nextInt();
}
for (int j = 0; j < allocation.length; j++) {
allocation[j] = new Resources(av[j].name, allocationResNum[j]);
}
System.out.println();
pcbs[i] = new PCB(name, max, allocation);
System.out.println("第" + (i+1) + "个进程初始化完毕");
}
boolean key = true;
while (key) {
bank banker = new bank(av, pcbs);
banker.resAllocation();//算法的实现
System.out.println();
//一般如果不安全的话 就需要继续申请资源 然后避免死锁的是实现
System.out.println("是否需要再次申请资源: 是请输入1 不请输入0");
int x = sc.nextInt();
if (x == 0) {
key = false;
} else {
System.out.println("输入需要申请资源的进程名");
String name = sc.next();
System.out.println("输入要申请的资源的数量");
int[] need = new int[num];
for (int i = 0; i < num; i++) {
need[i] = sc.nextInt();
}
System.out.println();
for (PCB p : pcbs
) {
p.finish = false;
//看一下的name是否相等 相等后才可以分配
if (p.name.equals(name)) {
for (int i = 0; i < p.allocation.length; i++) {
p.allocation[i].num += need[i];
}
}
}
System.out.println("---再次申请资源完毕,开始分配--");
}
}
}
}
890

被折叠的 条评论
为什么被折叠?



