Java实现银行家算法
前言
本文参考了还我瓶邪这位博主的代码,在此基础上做了一些修改,改成需要从键盘输入获得资源数目和进程数目以及初始情况下的可用资源量
银行家算法概述
避免死锁算法中最有代表性的算法是Dijkstra E.W 于1968年提出的银行家算法:
银行家算法是避免死锁的一种重要方法,防止死锁的机构只能确保上述四个条件之一不出现,则系统就不会发生死锁。通过这个算法可以用来解决生活中的实际问题,如银行贷款等。
程序实现思路银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要应多个客户的借贷周转,为了防止银行家资金无法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。在操作系统中研究资源分配策略时也有类似问题,系统中有限的资源要供多个进程使用,必须保证得到的资源的进程能在有限的时间内归还资源,以供其他进程使用资源。如果资源分配不得到就会发生进程循环等待资源,则进程都无法继续执行下去的死锁现象。
把一个进程需要和已占有资源的情况记录在进程控制中,假定进程控制块PCB其中"状态"有就绪态、等待态和完成态。当进程在处于等待态时,表示系统不能满足该进程当前的资源申请。"资源需求总量"表示进程在整个执行过程中总共要申请的资源量。显然,每个进程的资源需求总量不能超过系统拥有的资源总数, 银行算法进行资源分配可以避免死锁。
主要思路
1.初始化
由用户输入数据,分别对可利用资源向量矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION、需求矩阵NEED赋值。
2.进行银行家算法
银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。
设进程cusneed提出请求REQUEST[i],则银行家算法按如下规则进行断。
(1)如果REQUEST [cusneed] [i]<= NEED[cusneed][i],则转(2);否则,出错。
(2)如果REQUEST [cusneed] [i]<= AVAILABLE[cusneed][i],则转(3);否则,出错。
(3)系统试探分配资源,修改相关数据:
AVAILABLE[i]-=REQUEST[cusneed][i];
ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];
NEED[cusneed][i]-=REQUEST[cusneed][i];
(4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。
2.进入安全性算法
(1)设置两个工作向量Work=AVAILABLE;FINISH
(2)从进程集合中找到一个满足下述条件的进程,
FINISH==false;
NEED<=Work;
如找到,执行(3);否则,执行(4)
(3)设进程获得资源,可顺利执行,直至完成,从而释放资源。
Work+=ALLOCATION;
Finish=true;
返回步骤(2)
(4)如所有的进程Finish=true,则表示安全;否则系统不安全。
操作系统安全状态和不安全状态:
安全序列是指一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。
如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。
不存在一个安全序列则表示不安全。不安全状态不一定导致死锁。
程序流程图
源代码
import java.util.Scanner;
public class Bank {
private int[] Available; //用来存系统初始状态未分配时的可用资源量
private int[][] Max; //用来存取进程最大需求矩阵
private int[][] Alloction; //用来存取进程已经分配资源的矩阵
private int[][] Need; //用来存取各进程还需要的资源的矩阵
private int[][] Request; //用来存取用户输入的要检测的进程号和各类资源
private int[] Work; //用来检测系统安全性的
private int resource;
private int thread;
int num = 0; //进程编号(全局变量)
Scanner input = new Scanner(System.in);
public Bank(int resource,int thread){ //初始化
this.resource = resource;
this.thread = thread;
Available = new int[resource];
Max = new int[thread][resource];
Alloction = new int[thread][resource];
Need = new int[thread][resource];
Request = new int[thread][resource];
Work = new int[resource];
}
/**
* 设置可用资源量
*/
public void setAvailable(){
System.out.println("初始系统可用资源量Available:");
for(int i = 0;i<resource;i++){
Available[i] = input.nextInt();
}
}
/**
* 设置各初始系统变量,并判断是否处于安全状态。
*/
public void setMatrixVariable(){ //设置各类矩阵变量的方法
setMax(); //调用设置各进程的最大需求矩阵Max
setAlloction(); //调用各进程分配矩阵Alloction,
printMatrixVariable();//调用打印设置好的各类矩阵
Safe(); //调用安全性算法检测
}
/**
* 设置Max矩阵
*/
public void setMax() {
System.out.println("请设置各进程的最大需求矩阵Max:");
for (int i = 0; i < thread; i++) {
System.out.println("请输入进程P" + i + "的最大资源需求量:");
for (int j = 0; j < resource; j++) {
Max[i][j] = input.nextInt();
}
}
}
/**
* 设置已分配矩阵Alloction
*/
public void setAlloction() {
System.out.println("请设置请各进程分配矩阵Alloction:");
for (int i = 0; i < thread; i++) {
System.out.println("请输入进程P" + i + "的分配资源量:");
for (int j = 0; j < resource; j++) {
Alloction[i][j] = input.nextInt();
}
}
System.out.println("Available=Available-Alloction.");
System.out.println("Need=Max-Alloction.");
for (int i = 0; i < resource; i++) {//设置Available矩阵
for (int j = 0; j < thread; j++) {
Available[i] = Available[i] - Alloction[j][i];
}
}
for (int i = 0; i < thread; i++) {//设置Need矩阵
for (int j = 0; j < resource; j++) {
Need[i][j] = Max[i][j] - Alloction[i][j];
}
}
}
/**
* 把初始化或设置好的各矩阵打印出来
*/
public void printMatrixVariable(){
System.out.println("此时资源分配量如下:");
System.out.println("进程 \t"+ "Max\t"+" Alloction\t"+" Need\t"+ " Available");
for(int i=0;i<thread;i++){
System.out.print("P"+i+" ");
for(int j=0;j<resource;j++){
System.out.print(Max[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<resource;j++){
System.out.print(Alloction[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<resource;j++){
System.out.print(Need[i][j]+" ");
}
System.out.print("| ");
if(i==0){
for(int j=0;j<resource;j++){
System.out.print(Available[j]+" ");
}
}
System.out.println();
}
}
/**
* 设置请求资源量Request
*/
public void setRequest() {
System.out.println("请输入请求资源的进程编号:");
num= input.nextInt();//设置全局变量进程编号num
System.out.println("请输入请求各资源的数量:");
for (int j = 0; j < resource; j++) {
Request[num][j] = input.nextInt();
}
BankerAlgorithm();//调用银行家算法
}
/**
* 实现银行家算法功能
*/
public void BankerAlgorithm() {
boolean T=true;
for (int i = 0; i < resource; i++) {
if (Request[num][i] <= Need[num][i]) {
if (Request[num][i] <= Available[i]) {
Available[i] -= Request[num][i];
Alloction[num][i] += Request[num][i];
Need[num][i] -= Request[num][i];
} else {
System.out.println("当前没有足够的资源可分配,进程P" + num + "需等待。");
T = false;
}
} else {
System.out.println("进程P" + num + "请求已经超出最大需求量Need.");
T = false;
}
}
if(T==true){
printMatrixVariable();
System.out.println("现在进入安全算法:");
Safe();
}
}
/**
* 实现安全性检查功能
*/
public void Safe() {//安全算法
boolean[] Finish = new boolean[thread];//初始化Finish
for(int i = 0;i<thread;i++){
Finish[i] = false;
}
int count = 0; //完成进程数
int circle= 0; //循环圈数
int num1 = 0;
int[] S=new int[thread]; //安全序列
for (int i = 0; i < resource; i++) { //设置工作向量
Work[i] = Available[i];
}
System.out.println("进程 \t"+"Work\t"+ " Alloction\t"+" Need\t"+" Work+Alloction");
while (count < thread) {
for (int i = 0; i < thread; i++) {
for (int a = 0; a < resource; a++) {
if (Finish[i] == false && Need[i][a] <= Work[a]) {//判断条件
num1++;
}
}
if(num1 == resource){ //如果该进程的每个资源都满足need<=work,则该进程可以被分配
System.out.print("P" + i + " ");
for (int k = 0; k < resource; k++) {
System.out.print(Work[k] + " ");
}
System.out.print("| ");
for (int j = 0; j < resource; j++) {
Work[j] += Alloction[i][j];
}
Finish[i] = true;//当前进程能满足时
S[count] = i;//设置当前序列排号
count++;//满足进程数加1
for (int j = 0; j < resource; j++) {
System.out.print(Alloction[i][j] + " ");
}
System.out.print("| ");
for (int j = 0; j < resource; j++) {
System.out.print(Need[i][j] + " ");
}
System.out.print("| ");
for (int j = 0; j < resource; j++) {
System.out.print(Work[j] + " ");
}
System.out.println();
}num1 = 0;
}
circle++;//循环圈数加1
if(count==thread){//判断是否满足所有进程需要
System.out.print("此时存在一个安全序列:");
for (int i = 0; i<thread;i++){//输出安全序列
System.out.print("P"+S[i]+" ");
}
System.out.println("故当前可分配!");
break;//跳出循环
}
if(count<circle){//判断完成进程数是否小于循环圈数
count=Integer.MAX_VALUE;//设置一个不可能的数跳出循环
System.out.println("尝试分配后当前系统处于不安全状态,故不存在安全序列。所以应该取消分配!!");
System.out.println("----------------------------------------------------------------");
for (int i = 0; i < resource; i++) {
Available[i] += Request[num][i]; //如果不存在安全序列就撤销分配
Alloction[num][i] -= Request[num][i];
Need[num][i] += Request[num][i];
}
printMatrixVariable();
//break;//跳出循环
}
}
}
}
import java.util.Scanner;
public class TestDemo {
public static void main(String[] args) {
boolean Choose = true; // 用来控制是否继续的循环
final String C = "n"; //字符串常量
String Choice; //用来保存用户的选择
Scanner input = new Scanner(System.in);
System.out.println("请输入进程数目和资源数目");
int thread = input.nextInt();
int resource = input.nextInt();
Bank bank = new Bank(resource,thread); //创建一个Bank类的对象
bank.setAvailable();
bank.setMatrixVariable(); //调用方法初始化各类矩阵
while (Choose == true) {
bank.setRequest();
System.out.println("您是否还要进行请求:Y(y)/N(n)?");
Choice = input.nextLine();
if (C.equalsIgnoreCase(Choice)) { //忽略大小写
System.out.println("已成功退出程序!");
Choose = false;
}
}
input.close();
}
}
运行结果