【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
分析了一下银行家算法,基于银行家算法做了一个小程序.
银行家算法主要用于操作系统进程管理程序中,用于防止死锁.
接下来这段代码将模拟这一过程.
首先让我们知道银行家算法在进程资源分配中主要做什么:
进程管理系统掌控着操作系统的一切资源.几乎每个进程都要向操作系统索要资源.但是系统的资源又有限.试想:
当操作系统掌握A,B资源,有进程P1,P2,同一时刻,P1和P2都向操作系统索取AB两个资源,而操作系统却把A分给了P1,B分给了P2,这个时候P1和P2只占有一半资源,如果它们不释放,那么这两个进程就会进入死锁状态,在系统中无休止地请求资源.
为了解决这种问题,银行家算法被应用到进程管理系统中,值得注意的是,之所以叫做银行家算法,是因为这个算法最早被应用于银行向客户贷款的案例中,银行需要分析贷款是否安全,即一段时间内满足所有客户.
算法主要过程如下:
1.数据结构
Max矩阵,行号表示进程,列号表示进程所需的最大资源数目.
Allocation矩阵,行号表示进程号,列表示已经分配给进程的资源.
Need矩阵,表示仍然需要的资源数.Need由Max - Allocation得到.
Available向量,用于表示当前系统中可分配的资源.初始化为OS所有可分配资源.
以上数据结构可用1维和2维数组表示.非常简单.
2.银行家算法
1.某进程某时刻向操作系统索要资源,用Request(i)表示,如果系统中有3类资源,则Request(1) = {1,2,3}表示进程1向系统所有A:1 B:2 C:3.
2.如果Request(i)[ j ] <= Need[i, j]则进入第3步.(i表示进程号,j是资源类,按照3类资源,这里的j该是0,1,2 ),否则报错.
3.同样,如果Request < Available,跳向4,否则报错.
4.系统尝试将资源分配给P(i),然后修改数据结构的值:
Available -= Request ( 向量的减法应该会吧? 就是每个元数据相减.)
Allocation += Request
Need -= Request
5.执行安全检查,若可得出安全序列,则分配给进程资源.若得不出,说明分配资源给该进程是不安全的行为,可能导致死锁,让该进程的请求挂起,稍后再尝试.
安全检查步骤:
1.将Available复制一份儿,命名Work.,为所有进程设置一个Finish向量,默认初始化为false.
2.从进程中找出一个进程,Finish为false,Need <= Work.若找到执行3,否则4.
3.当进程获取到资源,执行完毕,然后将它持有的所有资源都会释放掉.
Work = Work + Allocation
Finish = true
跳转到第二步
4.如果所有Finish的元数据都为true,说明所有进程都能执行完毕,则表示系统处于安全状态.否则,不安全.
(安全序列在安全检查过程中得出.即一个能够执行完所有进程的进程号顺序.这个序列是不唯一的,找到一个即可.)
3.算法实现代码
1.数据结构
//max,need,allocation use matrix to express.
private static int[][] Max;
private static int[][] Allocation;
private static int[][] Need;
//about safety.
private static int[] Work;
private static boolean[] Finish;
private static int[] safeSequence;
private static int seqCounter = 0;
//the resources can be allocated that os handled
private static int[] Available;
private static int processCount = 0;
private static int resourceCount = 0;
private static int[] Request;
2.实现模拟分配资源:
//when OS ready,allocate resource to process
private static boolean allocateRequest(int process){
if(process < 0) return false;
//1,2.judge Request amount whether is illegal
for(int j = 0; j < resourceCount; j++){
if(Request[j] > Need[process][j]){
System.out.println("Request amount is over your Need");
return false;
}
if(Request[j] > Available[j]){
System.out.println("Request amount is over the amount that OS handled");
return false;
}
}
//3.allocate the resource to process.
for(int j = 0; j < resourceCount; j++){
Available[j] -= Request[j];
Allocation[process][j] += Request[j];
Need[process][j] -= Request[j];
}
return true;
}
3.实现安全分析:
//banker algorithm to check whther safe.
//if safe,return a serial key.else return null;
private static int[] checkSafety(){
//init safeSequence
safeSequence = new int[processCount];
seqCounter = 0;
//1.copy Available to Work.init Finish to false
Work = Available.clone();
Finish = new boolean[processCount];
int process; //no process choosed.
while(true){
process = -1;
//2.find a process like this finish = false, need < work.
for(int i = 0; i < processCount; i++){
if(Finish[i] == false){
//compare need[i,j] <work[j].i-process number, j-resource number.
for(int j = 0; j < resourceCount; j++){
if(Need[i][j] > Work[j]){
process = -1;
break;
}
process = i;
}
if(process != -1){
safeSequence[seqCounter++] = i;
break;
}
}else{
process = -1;
}
}
if(process != -1){
//3.if found,work = work + allocatation , finish = true. to step 2.
//P[process] exe. and realise the resource,after.
for(int j = 0; j < resourceCount; j++){
Work[j] += Allocation[process][j];
}
Finish[process] = true;
}else{
//4.if finish all is true.safe! else unsafe.
for(int i = 0; i < processCount; i++){
if(Finish[i] == false)
return null;
}
return safeSequence;
}
}
}
案例分析:
就图中的表我们使用以上算法代码进行分析:
表中数据:5个进程
Max矩阵为
其它请参照模糊的表.
分析过程(代码最后放出.):
1.首先我们输入有多少个进程和多少种资源,这里输入5,3:
2.初始化的Available,即系统还未分配的资源和已经分配的资源的总和(这里由表相加可知为 10 5 7):
3
3.接着输入Max矩阵:
4.接着输入Allocation矩阵:
5.程序自行计算出Need矩阵.和新的Availble资源:
6.测试当前状态的安全性:
7.模拟请求,假设现在0号进程需要请求资源以完成任务,请求的资源数为系统总资源数:
程序尝试分配给进程0资源,但是分配给进程后,发现当前的进程都无法顺利执行完毕,因此最后撤销了分配.
8.我们尝试重新分配,假设1号进程齐宁求{1,2,2}:
分配成功,分配成功后系统资源数目已发生变化,不会再revoke.
下面贴出整个冗余到不能再冗余的代码:
/*
*use java to realise banker algorithm.
*@author mrruan(RuanKun) qkmc@outlook.com
*/
import java.util.Scanner;
import java.lang.Math;
class Banker{
//max,need,allocation use matrix to express.
private static int[][] Max;
private static int[][] Allocation;
private static int[][] Need;
//about safety.
private static int[] Work;
private static boolean[] Finish;
private static int[] safeSequence;
private static int seqCounter = 0;
//the resources can be allocated that os handled
private static int[] Available;
private static int processCount = 0;
private static int resourceCount = 0;
private static int[] Request;
public static void main(String[] args){
Scanner scn = new Scanner(System.in);
System.out.println("Welcome To Bank Algorithm Program");
System.out.println("note:this is a algorithm to test safety about multi process");
//1.user input the process num and resource num.
System.out.println("please input how many processes will be handled:");
//no any process to deal with exceptions.
processCount = scn.nextInt();
System.out.println("please input how many kind of resources will be handled:");
resourceCount = scn.nextInt();
//init martrix
initMatrix(processCount, resourceCount);
//2.input the amount of resources that OS has.
System.out.println("please input every amount of the " + resourceCount + " resources(" + resourceCount + " integers,space to seperate)");
for(int i = 0; i < resourceCount; i++){
//init os resources
if(scn.hasNextInt())
Available[i] = scn.nextInt();//didn't check the safety,may cause exceptions.
}
System.out.println("now you have the resources and amount:");
for(int i = 0; i < resourceCount; i++){
System.out.print((char)(i+65)+ "."+Available[i]+" ");
}
//3.input Max matrix
System.out.println("\n this step you must input the max resources that every process can handle!");
for(int i = 0; i < processCount; i++){
System.out.println("input P" + i + " 's max handle resources("+resourceCount+" integers,space to seperate):");
System.out.print("P" + i + ": ");
for(int j = 0; j < resourceCount; j++){
Max[i][j] = scn.nextInt();
}
}
//we should judge if the max needed is out of the resources that os has.
for(int i = 0; i < processCount; i++){
for(int j = 0; j < resourceCount; j++){
try{
if(Max[i][j] > Available[j]){
//error, process cannot go on because the os cannot afford the resources that the process need.
throw new Exception("OS cannot afford the resources that the process needed.the error process is : P" + i);
}
}catch(Exception e){
e.printStackTrace();
return;
}
}
}
//print the max matrix.
System.out.println("this is the max matrix:");
for(int i = 0; i < processCount; i++){
for(int j = 0; j < resourceCount; j++)
System.out.print(Max[i][j] + " ");
System.out.println();
}
//4.now set the resources that processes had handled.
System.out.println("this step is to allocate the resources to every process.");
for(int i = 0; i < processCount; i++){
System.out.println("please input th process P" + i + "'s resources," + resourceCount + " integers,space to seperate:");
for(int j = 0; j < resourceCount; j++){
Allocation[i][j] = scn.nextInt(); // had not check the exceptions.
}
}
//now check the Allocation whether is legal.
for(int i = 0; i < processCount; i++){
for(int j = 0; j < resourceCount; j++){
try{
if(Allocation[i][j] > Available[j]){
System.out.println(Allocation[i][j] + " " + Available[j]);
throw new Exception("Allocated an illegal amount of resource,the error process is P" + i);
}
if(Allocation[i][j] > Max[i][j])
throw new Exception("you allocated is out of Max.position is : P " + i + " the kind is :" + (char)(j+65));
}catch(Exception e){
e.printStackTrace();
return;
}
}
}
//check sum.
int tmp = 0; //this is for the follow checking.
for(int i = 0; i < resourceCount; i++){
for(int j = 0; j < processCount; j++){
tmp += Allocation[j][i];
}
try{
if(tmp > Available[i]){
throw new Exception("over resource,position is : " + (char)(i + 65));
}
}catch(Exception e){
e.printStackTrace();
return;
}
tmp = 0;
}
vectorMinusMatrix(Available,Allocation, processCount, resourceCount);
//print the allocated matrix.
System.out.println("this is the Allocation matrix:");
for(int i = 0; i < processCount; i++){
for(int j = 0; j < resourceCount; j++)
System.out.print(Allocation[i][j] + " ");
System.out.println();
}
System.out.println("this is the Available resources after allocatation:");
for(int j = 0; j < resourceCount; j++)
System.out.print(Available[j] + " ");
System.out.println();
//5.get still need matrix
Need = matrixMinusMatrix(Max, Allocation, processCount, resourceCount);
System.out.println("this is the Need matrix:");
for(int i = 0; i < processCount; i++){
for(int j = 0; j < resourceCount; j++)
System.out.print(Need[i][j] + " ");
System.out.println();
}
System.out.println("the multi process module has been set up.");
System.out.println("please select a option");
int sw;
while(true){
System.out.println("\n 1. check the state whether safe.");
System.out.println("2. try to allocate resources to process.");
sw = scn.nextInt();
switch(sw){
case 1:
if (checkSafety() != null){
System.out.println("it's safe. the safeSequence is ");
for(int i = 0; i < seqCounter; i++)
System.out.print(safeSequence[i] + " ");
}else{
System.out.println("it's unsafe.");
}
break;
case 2:
int process = -1;
Request = new int[resourceCount];
System.out.println("please input the process Number:");
process = scn.nextInt();
System.out.println("please input the requested amount of resource.(it's "+ resourceCount +" integers):");
for(int i = 0; i < resourceCount; i++){
Request[i] = scn.nextInt();
}
//then try to allocate the requested resource to process.
if(allocateRequest(process))
//check
if (checkSafety() != null){
System.out.println("after allocated,it's safe. the safeSequence is ");
for(int i = 0; i < seqCounter; i++)
System.out.print(safeSequence[i] + " ");
System.out.println();
}else{
System.out.println("after allocated,it's unsafe.");
//if unsafe,DO NOT allocate
if(revokeRequest(process)){
System.out.println("Revoked allocation");
}
}
break;
}
}
//6.should get a safe serial key.
}
/*
* other methods
*
*/
//create matrix and init.
private static void initMatrix(int processCount,int resourceCount){
Max = new int[processCount][resourceCount];
Allocation = new int[processCount][resourceCount];
Need = new int[processCount][resourceCount];
Available = new int[resourceCount];
}
//vector - matrix.
private static void vectorMinusMatrix(int[] vector, int[][] matrix, int row, int col){
int sum = 0;
//System.out.println("print martrix");
//for(int i = 0; i < row; i++)
// for(int j = 0; j < col; j++)
// System.out.print(matrix[i][j] + " ");
for(int i = 0; i < col; i++){
for(int j = 0; j < row; j++){
sum += matrix[j][i];
}
//System.out.println("------------------------------------\n"+"the sum is " + sum +"\n------------------------------------");
vector[i] -= sum;
sum = 0;
}
}
//two matrix minus.
private static int[][] matrixMinusMatrix(int[][] matrix1, int[][] matrix2, int row, int col){
int[][] rs = new int[row][col];
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
rs[i][j] = Math.abs(matrix1[i][j] - matrix2[i][j]);
}
}
return rs;
}
//judge whether a vector is bigger than another.
//if vector1 > vector2, that means vector1's every elem is bigger than vector2
private static boolean compareVector(int[] vector1, int[] vector2,int length){
for(int i = 0; i < length; i++){
if(vector1[i] < vector2[i])
return false;
}
return true;
}
//banker algorithm to check whther safe.
//if safe,return a serial key.else return null;
private static int[] checkSafety(){
//init safeSequence
safeSequence = new int[processCount];
seqCounter = 0;
//1.copy Available to Work.init Finish to false
Work = Available.clone();
Finish = new boolean[processCount];
int process; //no process choosed.
while(true){
process = -1;
//2.find a process like this finish = false, need < work.
for(int i = 0; i < processCount; i++){
if(Finish[i] == false){
//compare need[i,j] <work[j].i-process number, j-resource number.
for(int j = 0; j < resourceCount; j++){
if(Need[i][j] > Work[j]){
process = -1;
break;
}
process = i;
}
if(process != -1){
safeSequence[seqCounter++] = i;
break;
}
}else{
process = -1;
}
}
if(process != -1){
//3.if found,work = work + allocatation , finish = true. to step 2.
//P[process] exe. and realise the resource,after.
for(int j = 0; j < resourceCount; j++){
Work[j] += Allocation[process][j];
}
Finish[process] = true;
}else{
//4.if finish all is true.safe! else unsafe.
for(int i = 0; i < processCount; i++){
if(Finish[i] == false)
return null;
}
return safeSequence;
}
}
}
//when OS ready,allocate resource to process
private static boolean allocateRequest(int process){
if(process < 0) return false;
//1,2.judge Request amount whether is illegal
for(int j = 0; j < resourceCount; j++){
if(Request[j] > Need[process][j]){
System.out.println("Request amount is over your Need");
return false;
}
if(Request[j] > Available[j]){
System.out.println("Request amount is over the amount that OS handled");
return false;
}
}
//3.allocate the resource to process.
for(int j = 0; j < resourceCount; j++){
Available[j] -= Request[j];
Allocation[process][j] += Request[j];
Need[process][j] -= Request[j];
}
return true;
}
//warning:this method should be invoked after allocatation.
//or will happen uncaught error.
private static boolean revokeRequest(int process){
if(process < 0) return false;
for(int j = 0; j < resourceCount; j++){
Available[j] += Request[j];
Allocation[process][j] -= Request[j];
Need[process][j] += Request[j];
}
return true;
}
}