安全序列原理
需要分配的资源(MAX)
已经分配的资源(Allocation)
还需要分配的资源(Need)
可分配的资源(Available)
线程(T)
只有当全部线程都满足分配,才是安全序列;
如图:可分配的资源(2,3,3)
T4还需资源(2,2,1),(2,2,1)<(2,3,3)进行分配,T4满足后,可分配资源=T4已经分配的资源+上一次可分配的资源=(2,0,4)+(2,3,3)=(4,3,7);
同理,T5还需资源(1,1,0),进行分配,可分配资源=T5已经分配的资源+上一次可分配的资源=(3,1,4)+(4,3,7)=(7,4,11);
T1还需资源(3,4,7),进行分配,可分配资源=T1已经分配的资源+上一次可分配的资源=(2,1,2)+(7,4,11)=(9,5,13);
T2还需资源(1,3,3),进行分配,可分配资源=T2已经分配的资源+上一次可分配的资源=(4,0,2)+(9,5,13)=(13,5,15);
T3还需资源(0,0,6),进行分配,可分配资源=T5已经分配的资源+上一次可分配的资源=(4,0,5)+(13,5,15)=(17,5,20);
所以安全序列为T4 T5 T1 T2 T3 ;
安全序列不唯一
代码实现
import java.util.Scanner;
public class BankerAlgorithm {
//定义资源
//可用资源Availiable 一维数组
private static int[] availiable = new int[]{3,3,2};
//最大需求量(每个线程最大资源数)
private static int[][] max = new int[][]{{7,5,3}, {3,2,2}, {9,0,2}, {2,2,2}, {4,3,3}};
//已分配的资源(每个线程已分配的)
private static int[][] allocation = new int[][]{{0,1,0}, {2,0,0},{3,0,2},{2,1,1},{0,0,2}};
//每个线程还需要的资源数
private static int[][] need = new int[][]{{7,4,3}, {1,2,2}, {6,0,0}, {0,1,1},{4,3,1}};
private static void showData(){
System.out.println("线程号 Max Allocation Need");
System.out.println(" A B C A B C A B C");
for(int i=0; i<5; i++){
System.out.print(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(allocation[i][j]+" ");
}
System.out.print(" ");
for(int j=0; j<3; j++){
System.out.print(need[i][j]+" ");
}
System.out.println();
}
}
//分配数据 给定线程,给定该线程需要的资源数
public static boolean allocateData(int threadNum, int[] request){
//比较需要的资源数与可用资源的大小关系,大于则直接返回,不予分配
if(!(request[0] <= need[threadNum][0] && request[1] <= need[threadNum][1] && request[2] <= need[threadNum][2])){
System.out.println("请求的资源超过了所需要的资源数,分配错误");
return false;
}
if(!(request[0] <= availiable[0] && request[1] <= availiable[1] && request[2] <= availiable[2])){
System.out.println("尚无足够资源分配,必须等待");
return false;
}
//尝试分配资源给请求的线程
for(int i=0; i<3; i++) {
//可分配资源-请求资源数量
availiable[i] = availiable[i] - request[i];
//已分配资源+请求资源数量
allocation[threadNum][i] = allocation[threadNum][i] + request[i];
//还需要资源-请求资源数量
need[threadNum][i] = need[threadNum][i] - request[i];
//安全性检查 调用安全性算法 查询剩余资源能否满足剩下的线程执行
}
boolean flag = checkSafe();
if(flag == true){
System.out.println("能够安全分配");
return true;
}else{
System.out.println("不能够安全分配");
//恢复预分配的数据
for(int j=0; j<3; j++){
availiable[j] = availiable[j]+request[j];
allocation[threadNum][j] = allocation[threadNum][j]-request[j];
need[threadNum][j] = need[threadNum][j]+request[j];
}
return false;
}
}
//安全性检查
public static boolean checkSafe(){
//找一个能够满足的线程,完成执行后去执行下一个线程
int i = 0;//线程号
boolean finish[] = new boolean[5]; //表示每个线程是否执行成功的标识
while(i<5){
//线程执行成功之后拿到一个属于自己的标识
if(finish[i] == false && need[i][0] <= availiable[0] && need[i][1] <= availiable[1] && need[i][2] <= availiable[2]){
System.out.println("可以分配,执行成功的线程为"+i);
finish[i] = true;
//分配资源之后当前线程执行成功,释放自己之前拥有的资源
for(int j=0; j<3; j++){
availiable[j] = availiable[j] + allocation[i][j];
}
//当前线程执行完,从头开始找一个新的可分配资源能够满足的线程
i = 0;
} else{
i++;
}
}
//判断每个线程的标识,如果标识都是执行成功的标识,则返回true
for(i=0; i<5; i++){
if(finish[i] == false){
//反之返回false
return false;
}
}
return true;
}
public static void main(String[] args) {
showData();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要请求的线程号:");
int threadNum = scanner.nextInt();
int request[] = new int[3];
String[] sources = new String[]{"A", "B", "C"};
System.out.println("请输入要请求的资源数目:");
for(int i=0; i<3; i++){
System.out.println("请输入"+sources[i]+"类资源的数目: ");
request[i] = scanner.nextInt();
}
//请求资源
allocateData(threadNum, request);
}
}