用JAVA来模拟实现银行家算法
此代码每一行代码都是我自己动手实现的,如果有写不好的,或者有错误的地方还请大家指出。
如果对该算法或者java的基础语法不熟悉的同学可以先去看看其他博客:
银行家算法推荐博客
银行家算法的图解(也是转自上述博客):
实验目的:
- 加深对死锁概念的理解
- 能够利用银行家算法,有效避免死锁的发生,或者检测死锁的存在
实验内容:
实验要求用高级语言编写和调试一个简单的银行家算法程序。加深了解有关资源申请、避免死锁等概念,并体会和了解死锁和避免死锁的具体实施方法。
- 设计进程对各类资源最大申请表示及初值确定。
- 设定系统提供资源初始状况。
- 设定每次某个进程对各类资源的申请表示。
- 编制程序,依据银行家算法,决定其申请是否得到满足。
实验分析及其过程:
1. 建立好程序的整体结构,创建四个类
Main: 主类,用于实例化银行家对象,然后调用对应的银行家安全算法
Bank: 银行家类,在该类中主要实现的就是银行家算法
Processor: 进程类,在该类中定义了进程所需要的属性
Sources: 资源类,在该类中定义了三种资源
2. 根据实验给出的测试数据初始化5
个进程 3
个资源
3. 在Main
中实例化Bank
对象,然后调用其中的银行家算法
对算法的简单解释(具体在注释中):
银行家算法的作用是进程在向系统请求资源的时候,预先判断会不会造成死锁,对应到这个算法就是判断能不能形成安全序列,
若能形成安全序列,则对该进程进行资源的分配,
若不能,则不进行资源分配
实验代码:
Main.java
:
/** 用于测试和调试银行家算法 */
public clss Main {
public static void main(String[] args) {
/** 开始调用银行家算法进行资源请求(判断是不是能形成一个安全序列) */
//银行家对象
Bank banker = new Bank();
//通过对象调用银行家算法
banker.BankAlgorithm();
}
}
Processor.java:
/** 进程类 */
public class Processor {
/** 四个字段 */
private String name;//进程名字
Sources max;//进程所需要的最大资源
Sources allocation;//当前进程已经分配的资源数
Sources need;//当前进程还需要多少资源(max-allocation)
public boolean Finish = false;//判断进程是否结束
public Processor(String name, int max_a,int max_b,int max_c,int all_a,int all_b,int all_c,int need_a,int need_b,int need_c)
{
this.name = name;
max = new Sources(max_a,max_b,max_c);
allocation = new Sources(all_a,all_b,all_c);
need = new Sources(need_a,need_b,need_c);
}
public void ShowProcessor()
{
//打印出进程的信息
System.out.println(name+"\t"+max.toString()+"\t\t"+allocation.toString()+"\t\t\t"+need.toString());
}
}
Sources.java:
/** 资源类 */
public class Sources {
/** 三个字段分别表示A.B.C这三类资源 */
public int A;
public int B;
public int C;
public Sources() {
}
public Sources(int A,int B,int C) {
this.A = A;
this.B = B;
this.C = C;
}
public String toString()
{
//打印出资源信息
return A+" "+B+" "+C;
}
}
Bank.java:
/** 银行家算法主体类: */
public class Bank
{
/** 分配资源的方法:将进程的资源请求进行处理 */
public void BankAlgorithm()
{
/** 初始化系统已有的资源 + 五个进程的当前信息 */
// 五个进程对象(输入每个进程对象的名称\所需的最大资源\已分配的资源\还需要的资源)
Processor processor[] = new Processor[5];
/** 第一组测试数据: */
processor[0] = new Processor("P0", 5, 7, 3, 1, 0, 0, 4, 7, 3);
processor[1] = new Processor("P1", 2, 3, 2, 0, 2, 0, 2, 1, 2);
processor[2] = new Processor("P2", 0, 9, 2, 0, 3, 2, 0, 6, 0);
processor[3] = new Processor("P3", 2, 2, 2, 1, 2, 1, 1, 0, 1);
processor[4] = new Processor("P4", 3, 4, 3, 0, 0, 2, 3, 4, 1);
/** 第二组测试数据:
processor[0] = new Processor("P0", 5, 7, 3, 1, 0, 0, 4, 7, 3);
processor[1] = new Processor("P1", 2, 3, 2, 0, 2, 0, 2, 1, 2);
processor[2] = new Processor("P2", 0, 9, 2, 0, 3, 2, 0, 6, 0);
processor[3] = new Processor("P3", 2, 2, 2, 1, 2, 1, 1, 0, 1);
processor[4] = new Processor("P4", 3, 4, 3, 3, 3, 3, 0, 1, 0);*/
// 一个资源对象(表示当系统拥有的资源)
Sources sources = new Sources(3, 3, 2);
System.out.println("当前系统可分配资源为:");
System.out.println("A: " + sources.A + "\tB: " + sources.B + "\tC: " + sources.C);
System.out.println("----------------------------进程状态" + "------------------------------");
System.out.println("P(进程号)" + "\t" + "Max(所需最大资源)" + "\t" + "Allocation(已分配资源)" + "\t" + "Need(还需要的资源数量)");
System.out.println(" " + "\t" + "A B C" + "\t\t" + "A B C" + "\t\t\t" + "A B C");
for (int i = 0; i < 5; i++)
{
processor[i].ShowProcessor();
}
System.out.println("-----------------------------------------------------------------\n");
while (true)
{
System.out.println("开始进程资源分配:");
// 输入要请求的进程号及其要请求的资源数目
Scanner scan = new Scanner(System.in);
System.out.println("请输入要请求的进程号(0-4): ");
int RequestProcessorNum = scan.nextInt();
System.out.println("请输入要为该进程请求的资源数目(A、B、C): ");
int a, b, c;
a = scan.nextInt();
b = scan.nextInt();
c = scan.nextInt();
Sources RequestSources = new Sources(a, b, c);
// 当初始时第一个进程请求完毕后,需要做判断和改值
// 1.判断是不是保证请求的每个资源数量是小于等于该进程还需要的资源数量的
if (RequestSources.A > processor[RequestProcessorNum].need.A
|| RequestSources.B > processor[RequestProcessorNum].need.B
|| RequestSources.C > processor[RequestProcessorNum].need.C) {
System.out.println("出现错误: 请求的资源超过了该进程所需要的资源");
System.out.println("退出系统");
System.exit(-1);
}
// 2.判断请求的资源是不是小于等于当前所拥有的资源
if (RequestSources.A > sources.A || RequestSources.B > sources.B || RequestSources.C > sources.C) {
System.out.println("出现错误: 请求的资源超过了系统此时拥有的资源");
System.out.println("退出系统(等待其他进程释放资源)");
System.exit(-1);
}
// 工作资源(实时记录当前系统资源数量)
Sources Work = new Sources(3,3,2);
//因为已经有进程请求了分配资源,假设可以进行这次的资源请求,所以需要改值
processor[RequestProcessorNum].allocation.A += RequestSources.A;
processor[RequestProcessorNum].allocation.B += RequestSources.B;
processor[RequestProcessorNum].allocation.C += RequestSources.C;
processor[RequestProcessorNum].need.A -= RequestSources.A;
processor[RequestProcessorNum].need.B -= RequestSources.B;
processor[RequestProcessorNum].need.C -= RequestSources.C;
Work.A -= RequestSources.A;
Work.B -= RequestSources.B;
Work.C -= RequestSources.C;
//已经做出了资源请求并且改了值,判断是不是存在安全序列
boolean isExistSafeQueue = true;
String[] safeQueue = new String[5];
int index = 0;
while (true)
{
boolean find = false;
for (int i = 0; i < 5; i++)
{
if (processor[i].Finish == false)// 该进程没有分配资源
{
boolean flag = true;// 看系统当前资源是不是>=该进程需要的资源
if (Work.A < processor[i].need.A)
{
flag = false;
}
if (Work.B < processor[i].need.B)
{
flag = false;
}
if (Work.C < processor[i].need.C)
{
flag = false;
}
if (flag == true)
{
//System.out.println("此时进程"+i+"可以被分配资源");
// 满足三个资源的条件,可以进行资源的分配,当前系统的资源要+上该进程释放的资源
Work.A += processor[i].allocation.A;
Work.B += processor[i].allocation.B;
Work.C += processor[i].allocation.C;
//System.out.println("分配资源后work数组等于="+Work.A+","+Work.B+","+Work.C);
processor[i].Finish = true;
// 安全序列中加入这个进程
safeQueue[index++] = "P" + i;
// 标记find
find = true;
}
}
}
if (find == false)
{
for (int i = 0; i < 5; i++)
{
if (processor[i].Finish == false)
{
isExistSafeQueue = false;
System.out.println("出现进程之间的死锁,也就是找不到安全序列");
break;
}
}
break;
}
}
// 如果存在安全序列
if (isExistSafeQueue == true)
{
System.out.println("能够对进程安全分配资源");
System.out.println("安全序列如下:");
for (int i = 0; i < 5; i++)
{
System.out.print(safeQueue[i] + " ");
}
System.out.println();
//已经判断能够形成安全序列,表示该进程的资源请求成功,此时不需要改变进程的值只要改变sources的值解
sources.A -= RequestSources.A;
sources.B -= RequestSources.B;
sources.C -= RequestSources.C;
System.out.println("\n系统分配资源后:");
System.out.println("当前系统可分配资源为:");
System.out.println("A: " + sources.A + "\tB: " + sources.B + "\tC: " + sources.C);
System.out.println("----------------------------进程状态" + "------------------------------");
System.out.println(
"P(进程号)" + "\t" + "Max(所需最大资源)" + "\t" + "Allocation(已分配资源)" + "\t" + "Need(还需要的资源数量)");
System.out.println(" " + "\t" + "A B C" + "\t\t" + "A B C" + "\t\t\t" + "A B C");
for (int i = 0; i < 5; i++)
{
processor[i].ShowProcessor();
}
System.out.println("-----------------------------------------------------------------\n");
}
else
{
System.out.println("不能够对进程进行安全的资源分配");
//已经判断不能够形成安全序列,表示该进程的资源请求失败,因为之前已经修改了值,所以要改回来
processor[RequestProcessorNum].allocation.A -= RequestSources.A;
processor[RequestProcessorNum].allocation.B -= RequestSources.B;
processor[RequestProcessorNum].allocation.C -= RequestSources.C;
processor[RequestProcessorNum].need.A += RequestSources.A;
processor[RequestProcessorNum].need.B += RequestSources.B;
processor[RequestProcessorNum].need.C += RequestSources.C;
System.out.println("当前系统可分配资源为:");
System.out.println("A: " + sources.A + "\tB: " + sources.B + "\tC: " + sources.C);
System.out.println("----------------------------进程状态" + "------------------------------");
System.out.println(
"P(进程号)" + "\t" + "Max(所需最大资源)" + "\t" + "Allocation(已分配资源)" + "\t" + "Need(还需要的资源数量)");
System.out.println(" " + "\t" + "A B C" + "\t\t" + "A B C" + "\t\t\t" + "A B C");
for (int i = 0; i < 5; i++)
{
processor[i].ShowProcessor();
}
System.out.println("-----------------------------------------------------------------\n");
}
System.out.println("是否还需要测试该算法(yes/no):");
String ask = scan.next();
if (ask.equals("no"))
{
break;
}
}
}
}
实验结果:
进程1申请(1,0,2) - 申请成功
进程4申请(3,3,1) - 死锁