1. 算法思想
银行家算法是为了避免死锁的算法,是Dijkstra的银行家算法。由于该算法用于实现银行系统现金贷款的发放而得名的。为实现银行家算法,系统中必须设置若干数据结构。
1) 银行家算法的数据结构
a) 可利用资源向量available
b) 最大需求矩阵
c) 分配矩阵
d) 需求矩阵
2) 银行家算法
设Requesti 是进程Pi的请求量,如果Requesti[j]=k,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查。
a) 如果Requesti[j] <=Need[I,j],便转向步骤(b);否则认为出错,因为他所需要的资源数已经超过它所宣布的最大值。
b) 如果Requesi[j] <=Available[j],便转向步骤(c);否则,表示尚无足够的资源,Pi须等待。
c) 系统试探着把资源分配给进程Pi,并修改下面的数据结构中的数值:
Available[j] := Available[j] – Request i[j];
Allocation[i, j] :=Allocation[i, j] + Request i[j];
Need[i, j] := Need[i, j] – Request i[j];
d) 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,已完成本次资源的分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
3) 安全算法
系统所执行的安全算法可描述如下:
(1) 设置两个向量:
① 工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work :=Available。
② Finish,他表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish := false;当有足够资源分配给进程时,再令Finish[i] :=true。
(2) 从进程集合中找到一个满足下述条件的进程:
① Finish[i] := false;
② Need[i, j] <= Work[j]; 若找到,执行步骤(3),否则,执行步骤(4)。
(3) 当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给他的资源,故应执行:
Work[j] :=Work[j] + Allocation[i, j];
Finish[i] :=true;
Go to step2;
(4) 如果所有进程的Finish[i] = true 都满足,则表示系统处于安全状态;否则,系统处于不安全状态。
import java.util.Scanner;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane.MaximizeAction;
import javax.swing.text.StyledEditorKit.ForegroundAction;
public class Banker {
static int available[]=new int[3]; //资源数
static int max[][]=new int[5][3]; //最大需求
static int allocation[][]=new int[5][3]; //分配
static int need[][]=new int[5][3]; //需求
static int request[]=new int[3]; //存放请求
Scanner scanner=new Scanner(System.in);
int thread; //线程号
//初始化
public void getData(){
System.out.println("请输入A,B,C三类资源的数目:");
//输入A,B,C三类资源数量
for(int i=0;i<3;i++){
available[i]=scanner.nextInt();
}
//输入进程对三类资源的最大需求
for(int i=0;i<5;i++){
System.out.println("请输入进程"+i+"对A,B,C三类资源的最大需求");
for(int j=0;j<3;j++){
max[i][j]=scanner.nextInt();
}
}
//输入进程分配的三类资源数
for(int i=0;i<5;i++){
System.out.println("请输入进程"+i+"已分配的A,B,C三类资源数");
for(int j=0;j<3;j++){
allocation[i][j]=scanner.nextInt();
}
}
//计算进程还需要的三类资源数
for(int i=0;i<5;i++){
for(int j=0;j<3;j++){
need[i][j]=max[i][j]-allocation[i][j];
}
}
//重新计算available
for(int i=0;i<3;i++){
for(int j=0;j<5;j++){
available[i]-=allocation[j][i];
}
}
}
//用户输入要申请资源的线程和申请的资源,并进行判断
public void getThread(){
System.out.println("请输入申请资源的线程");
int thread=scanner.nextInt(); //线程
if(thread<0||thread>4){
System.out.println("该线程不存在,请重新输入");
getThread();
}else{
this.thread=thread;
System.out.println("请输入申请的资源(三种,若某种资源不申请则填0)");
for(int i=0;i<3;i++){
request[i]=scanner.nextInt();
}
if(request[0]>need[thread][0]||request[1]>need[thread][1]||request[2]>need[thread][2]){
System.out.println(thread+"线程申请的资源超出其需要的资源,请重新输入");
getThread();
}else{
if(request[0]> available[0]||request[1]> available[1]||request[2]> available[2]){
System.out.println(thread+"线程申请的资源大于系统资源,请重新输入");
getThread();
}
}
changeData(thread);
if(check(thread)){
getThread();
}else{
recoverData(thread);
getThread();
}
}
}
//thread线程请求响应后,试探性分配资源
public void changeData(int thread){
for(int i=0;i<3;i++){
//重新调整系统资源数
available[i]-=request[i];
//计算各个线程拥有资源
allocation[thread][i]+=request[i];
//重新计算需求
need[thread][i]-=request[i];
}
}
//安全性检查为通过,分配失败时调用,恢复系统原状
public void recoverData(int thread){
for(int i=0;i<3;i++){
//重新调整系统资源数
available[i]+=request[i];
//计算各个线程拥有资源
allocation[thread][i]-=request[i];
//重新计算需求
need[thread][i]+=request[i];
}
}
//对线程thread安全性检查
public boolean check(int thread){
boolean finish[]=new boolean[5];
int work[]=new int[3];
int queue[]=new int[5]; //由于存放安全队列
int k=0;//安全队列下标
int j; //要判断的线程
int i;
//是否分配的标志
for(i=0;i<5;i++)
finish[i]=false;
j=thread;
for(i=0;i<3;i++){
work[i]=available[i];
}
while(j<5){
for( i=0;i<3;i++){
if(finish[j]){
j++;
break;
}else if(need[j][i]>work[i]){
//System.out.println(need[j][i]+"*"+i+work[i]);
j++;
break;
}else if(i==2){
for(int m=0;m<3;m++){
work[m]+=allocation[j][m];
}
finish[j]=true;
queue[k]=j;
k++;
j=0; //从最小线程再开始判断
}
}
}
//判断是否都属于安全状态
for(int p=0;p<5;p++){
if(finish[p]=false){
System.out.println("系统不安全,资源申请失败");
return false;
}
}
System.out.println("资源申请成功,安全队列为:");
for(int q=0;q<5;q++){
System.out.println(queue[q]);
}
return true;
}
//打印need和available,需要时调用
public void showData(){
System.out.println("need");
for(int i=0;i<5;i++){
for(int j=0;j<3;j++){
System.out.print(need[i][j]+" ");
}
}
System.out.println("available");
for(int j=0;j<3;j++){
System.out.print(available[j]+" ");
}
}
public static void main(String[] args) {
Banker bk=new Banker();
bk.getData();
bk.getThread();
}
}