这里参考了:
http://mp.weixin.qq.com/s?__biz=MzAwNzczMjk1NQ==&mid=400637315&idx=1&sn=f578bf6de58c1a57df07df310ae1ca1b&scene=1&srcid=0920DQXmm3IeDGyaJxxLz6oZ#wechat_redirect
http://blog.sina.com.cn/s/blog_7a4d0df90100zr6x.html
并针对Java实现需要对内容进行了修改。
银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金。
下面逐一简绍这三个过程:
一、初始化Init() 流程图:
由用户输入数据, 分别对 AVAILABLE , MAX , ALLOCATION , NEED 赋值。
二、安全性检查Safe() 流程图:
步骤:
1.设置两个工作向量 Work=AVAILABLE; FINISH
2.从进程集合中找到一个满足下述条件的进程,FINISH ==false; NEED <= Work;
如找到,执行(3);否则,执行(4)
3.设进程获得资源,可顺利执行,直至完成,从而释放资源。
Work += ALLOCATION; Finish=true;GOTO 2
4.如所有的进程Finish= true,则表示安全;否则系统不安全。
操作系统安全状态和不安全状态:
1.安全序列是指一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚 需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。
2.如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态 一定是没有死锁发生。
3.如果不存在一个安全序列, 不安全状态不一定导致死锁。
4.安全是指系统能找到一个序列使得所有资源得到分配。
三、银行家算法Bank() 流程
1.在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。
2.银行家算法的基本思想是分配资源之前, 判断系统是否是安全的; 若是, 才分配。它是最具有代表性的避免死锁的算法。
3.设进程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) 系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状。
具体的Java实现代码如下:
package bankerTest;
import java.util.Scanner;
public class BankerClass {
int[] Available = {10, 8, 7};
int[][] Max = new int[3][3];
int[][] Alloction = new int[3][3];
int[][] Need = new int[3][3];
int[][] Request = new int[3][3];
int[] Work = new int[3];
int num = 0;//进程编号
Scanner in = new Scanner(System.in);
public BankerClass() {
// Max={{6,3,2},{5,6,1},{2,3,2}};
}
public void setSystemVariable(){//设置各初始系统变量,并判断是否处于安全状态。
setMax();
setAlloction();
printSystemVariable();
SecurityAlgorithm();
}
public void setMax() {//设置Max矩阵
System.out.println("请设置各进程的最大需求矩阵Max:");
for (int i = 0; i < 3; i++) {
System.out.println("请输入进程P" + i + "的最大资源需求量:");
for (int j = 0; j < 3; j++) {
Max[i][j] = in.nextInt();
}
}
}
public void setAlloction() {//设置已分配矩阵Alloction
System.out.println("请设置请各进程分配矩阵Alloction:");
for (int i = 0; i < 3; i++) {
System.out.println("晴输入进程P" + i + "的分配资源量:");
for (int j = 0; j < 3; j++) {
Alloction[i][j] = in.nextInt();
}
}
System.out.println("Available=Available-Alloction.");
System.out.println("Need=Max-Alloction.");
for (int i = 0; i < 3; i++) {//设置Alloction矩阵
for (int j = 0; j < 3; j++) {
Available[i] = Available[i] - Alloction[j][i];
}
}
for (int i = 0; i < 3; i++) {//设置Need矩阵
for (int j = 0; j < 3; j++) {
Need[i][j] = Max[i][j] - Alloction[i][j];
}
}
}
public void printSystemVariable(){
System.out.println("此时资源分配量如下:");
System.out.println("进程 "+" Max "+" Alloction "+" Need "+" Available ");
for(int i=0;i<3;i++){
System.out.print("P"+i+" ");
for(int j=0;j<3;j++){
System.out.print(Max[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<3;j++){
System.out.print(Alloction[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<3;j++){
System.out.print(Need[i][j]+" ");
}
System.out.print("| ");
if(i==0){
for(int j=0;j<3;j++){
System.out.print(Available[j]+" ");
}
}
System.out.println();
}
}
public void setRequest() {//设置请求资源量Request
System.out.println("请输入请求资源的进程编号:");
num= in.nextInt();//设置全局变量进程编号num
System.out.println("请输入请求各资源的数量:");
for (int j = 0; j < 3; j++) {
Request[num][j] = in.nextInt();
}
System.out.println("即进程P" + num + "对各资源请求Request:(" + Request[num][0] + "," + Request[num][1] + "," + Request[num][2] + ").");
BankerAlgorithm();
}
public void BankerAlgorithm() {//银行家算法
boolean T=true;
if (Request[num][0] <= Need[num][0] && Request[num][1] <= Need[num][1] && Request[num][2] <= Need[num][2]) {//判断Request是否小于Need
if (Request[num][0] <= Available[0] && Request[num][1] <= Available[1] && Request[num][2] <= Available[2]) {//判断Request是否小于Alloction
for (int i = 0; i < 3; 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){
printSystemVariable();
System.out.println("现在进入安全算法:");
SecurityAlgorithm();
}
}
public void SecurityAlgorithm() {//安全算法
boolean[] Finish = {false, false, false};//初始化Finish
int count = 0;//完成进程数
int circle=0;//循环圈数
int[] S=new int[3];//安全序列
for (int i = 0; i < 3; i++) {//设置工作向量
Work[i] = Available[i];
}
boolean flag = true;
while (count < 3) {
if(flag){
System.out.println("进程 "+" Work "+" Alloction "+" Need "+" Work+Alloction ");
flag = false;
}
for (int i = 0; i < 3; i++) {
if (Finish[i]==false&&Need[i][0]<=Work[0]&&Need[i][1]<=Work[1]&&Need[i][2]<=Work[2]) {//判断条件
System.out.print("P"+i+" ");
for (int k = 0; k < 3; k++){
System.out.print(Work[k]+" ");
}
System.out.print("| ");
for (int j = 0; j<3;j++){
Work[j]+=Alloction[i][j];
}
Finish[i]=true;//当当前进程能满足时
S[count]=i;//设置当前序列排号
count++;//满足进程数加1
for(int j=0;j<3;j++){
System.out.print(Alloction[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<3;j++){
System.out.print(Need[i][j]+" ");
}
System.out.print("| ");
for(int j=0;j<3;j++){
System.out.print(Work[j]+" ");
}
System.out.println();
}
}
circle++;//循环圈数加1
if(count==3){//判断是否满足所有进程需要
System.out.print("此时存在一个安全序列:");
for (int i = 0; i<3;i++){//输出安全序列
System.out.print("P"+S[i]+" ");
}
System.out.println("故当前可分配!");
break;//跳出循环
}
if(count//判断完成进程数是否小于循环圈数
count=5;
System.out.println("当前系统处于不安全状态,故不存在安全序列。");
break;//跳出循环
}
}
}
}
package bankerTest;
import java.util.Scanner;
public class TestBankerClass {
public static void main(String[] args) {
// TODO code application logic here
boolean Choose = true;
String C;
Scanner in = new Scanner(System.in);
BankerClass T = new BankerClass();
System.out.println("这是一个三个进程,初始系统可用三类资源为{10,8,7}的银行家算法:");
T.setSystemVariable();
while (Choose == true) {
T.setRequest();
System.out.println("您是否还要进行请求:y/n?");
C = in.nextLine();
if (C.endsWith("n")) {
Choose = false;
}
}
}
}
运行结果如下:
这是一个三个进程,初始系统可用三类资源为{10,8,7}的银行家算法:
请设置各进程的最大需求矩阵Max:
请输入进程P0的最大资源需求量:
8 7 5
请输入进程P1的最大资源需求量:
5 2 5
请输入进程P2的最大资源需求量:
6 6 2
请设置请各进程分配矩阵Alloction:
晴输入进程P0的分配资源量:
3 2 0
晴输入进程P1的分配资源量:
2 0 2
晴输入进程P2的分配资源量:
1 3 2
Available=Available-Alloction.
Need=Max-Alloction.
此时资源分配量如下:
进程 Max Alloction Need Available
P0 8 7 5 | 3 2 0 | 5 5 5 | 4 3 3
P1 5 2 5 | 2 0 2 | 3 2 3 |
P2 6 6 2 | 1 3 2 | 5 3 0 |
进程 Work Alloction Need Work+Alloction
P1 4 3 3 | 2 0 2 | 3 2 3 | 6 3 5
P2 6 3 5 | 1 3 2 | 5 3 0 | 7 6 7
P0 7 6 7 | 3 2 0 | 5 5 5 | 10 8 7
此时存在一个安全序列:P1 P2 P0 故当前可分配!
请输入请求资源的进程编号:
0
请输入请求各资源的数量:
1 0 0
即进程P0对各资源请求Request:(1,0,0).
此时资源分配量如下:
进程 Max Alloction Need Available
P0 8 7 5 | 4 2 0 | 4 5 5 | 3 3 3
P1 5 2 5 | 2 0 2 | 3 2 3 |
P2 6 6 2 | 1 3 2 | 5 3 0 |
现在进入安全算法:
进程 Work Alloction Need Work+Alloction
P1 3 3 3 | 2 0 2 | 3 2 3 | 5 3 5
P2 5 3 5 | 1 3 2 | 5 3 0 | 6 6 7
P0 6 6 7 | 4 2 0 | 4 5 5 | 10 8 7
此时存在一个安全序列:P1 P2 P0 故当前可分配!
您是否还要进行请求:y/n?
y
请输入请求资源的进程编号:
2
请输入请求各资源的数量:
0 1 0
即进程P2对各资源请求Request:(0,1,0).
此时资源分配量如下:
进程 Max Alloction Need Available
P0 8 7 5 | 4 2 0 | 4 5 5 | 3 2 3
P1 5 2 5 | 2 0 2 | 3 2 3 |
P2 6 6 2 | 1 4 2 | 5 2 0 |
现在进入安全算法:
进程 Work Alloction Need Work+Alloction
P1 3 2 3 | 2 0 2 | 3 2 3 | 5 2 5
P2 5 2 5 | 1 4 2 | 5 2 0 | 6 6 7
P0 6 6 7 | 4 2 0 | 4 5 5 | 10 8 7
此时存在一个安全序列:P1 P2 P0 故当前可分配!
您是否还要进行请求:y/n?
n