银行家算法(Java)
系统安全状态
安全状态
指系统能按某种进程推进顺序(P1,P2,... ,Pn)未每个进程Pi分配器所需资源,直至满足每个进程对资源的最大需求,使每个进程都可以顺利的完成,此时成(P1,P2,...,Pn)为安全序列,没找到安全序列则说明系统处于不安全状态
只要系统处于安全状态就不会发生死锁,系统处于不安全状态就有可能会发生死锁
举例:
假定系统中有三个进程P1、P2、P3,共有12台磁带机。进程P1总共需要10 台磁带机,P2和P3 分别需要 4,9。假定在T0时刻,进程P1、P2、P3 分别已获得 5、2、2台磁带机,则还有三台尚未分配
进程 | 最大需求 | 已分配 | 可用 |
---|---|---|---|
P1 | 10 | 5 | 3 |
P2 | 4 | 2 | |
P3 | 9 | 2 |
那么T0 时刻系统是安全的,因为还有一个安全序列(P2,P1,P3)【先将两台磁带机分配给P2,P2执行完后释放所有磁带机,还剩下5台,然后全部分配给P1,执行完释放,再分配给P3】,所以我们称T0时刻系统是安全的
如果此时P3想再请求一个磁带机,这时需要考虑如果分配给P3一个磁带机后是否还能处于安全状态,如果不处于安全状态则不会分配给P3。(分配后已分配为 5、2、3,剩余2,如果全部分配给P2执行完释放也智能剩余4台磁带机,而P1还需要5台,P2还需要6台,显然不能完成执行)所以此时系统并不会将磁带机分配给P3,因为这会让系统处于不安全状态。
银行家算法
系统资源分配规则
- 每一个新进程进入系统时,他必须先声明在运行过程中可能需要请求的每种资源类型的最大单元数目,其数目不超过系统所拥有的资源总量
- 进程请求一组资源时,系统必须首先确定受否有足够的资源分配给该进程
- 如果有足够的资源分配,还需要计算将这些资源分配后是否会使系统处于不安全状态
- 只有当系统不会处于安全状态的时候才会将资源分配给进程,否则让进程等待
数据结构
- 系统可利用资源向量 Available。这时一个含有m个元素的数组,每个元素表示一类可利用的资源数目。初始值为 系统 的所有资源总量
- 最大需求矩阵 Max。这是一个 n * m 的矩阵,它定义了系统中 n 个进程中每一个进程对 m 类资源的最大需求(对应上表最大需求,只不过这里有 m 类资源,上表只描述一种)
- 分配矩阵 Allocation。这是一个 n * m 的矩阵,它定义了系统中 n 个进程中每一个进程对 m 类资源的当前分配量(对应上表已分配,只不过这里有 m 类资源,上表只描述一种)
- 需求矩阵 Need。这是一个 n * m 的矩阵,用以表示 n 个进程中每个进程对 m 类资源完成程序运行还需要的 数量(就是一个需求量 Need满足如后定义 Need = Max - Allocation ),这个矩阵方便计算
银行家算法
用 Request_i 表示进程 i 的请求资源向量,Request_i[j] = K 表示 进程 i 想要请求获取 第 i 类资源 K 个
public boolean isRequest(int[] Request_i, int i) throws InterruptedException {
for(int j = 0; j < Request_i.length; j++)
if(Request_i[j] > Need[i][j])
throw new RuntimeException("请求资源数量超过最大需求资源数量");
for(int j = 0; j < Request_i.length; j++)
if(Request_i[j] > Available[j]) {
synchronized(BankerAlgorithm.class) {
BankerAlgorithm.class.wait();
return false;
}
}
// 尝试分配资源
for(int j = 0; j < Request_i.length; j++) {
Available[j] -= Request_i[j];
Allocation[i][j] += Request_i[j];
Need[i][j] -= Request_i[j];
}
// 执行安全分析算法,如果安全则正是将资源分配给进程 Pi,以完成本次分配,否则本次的试探分配作废,恢复原来资源分配状态,让进程 Pi 等待
if(isSafety()){
System.out.println("安全:可用分配");
return true;
}
else{
for(int j = 0; j < Request_i.length; j++) {
Available[j] += Request_i[j];
Allocation[i][j] -= Request_i[j];
Need[i][j] += Request_i[j];
}
synchronized(BankerAlgorithm.class) {
BankerAlgorithm.class.wait();
return false;
}
}
}
安全性算法
先预定义向量 Work 和 布尔数组 Finish
Work表示可提供给进程据徐运行所需的各类资源数目 在执行算法之前初始化 Work = Available
当进程 Pi 满足系统资源分配时令 Finish[i] = true
public boolean isSafety(){
int[] Work = new int[Available.length];
boolean[] Finish = new boolean[Need.length];
for(int i = 0; i < Available.length; i++){
Work[i] = Available[i];
}
int unFinished = Finish.length; // 定义未完成的数量
int preUnFinished = -1; // 定义完成一次计算之后
while(unFinished != 0 && unFinished != preUnFinished){
preUnFinished = unFinished;
TASK: for(int i = 0; i < Finish.length; i++){
/*
* 如果该进程未完成,判断是不是所有的 Work[j] >= Need[i][j]
* 如果满足则假设执行完该进程,所以我们可用直接让 Work[j] += Need[i][j],
* 并标注已完成 Finish[i] = true;
* 未完成数量减1 unFinished--
*/
if(!Finish[i]){
for(int j = 0; j < Need[i].length; j++ ){
if(Work[j] < Need[i][j]){
//有一项不满足则直接跳过循环(因为已经不可能完成该进程)
continue TASK;
}
}
// 如果全部慢则则完成上述
for(int j = 0; j < Allocation[i].length; j++)
Work[j] += Allocation[i][j];
Finish[i] = true;
System.out.println(i);
unFinished--;
}
}
System.out.println("Work: " + Arrays.toString(Work));
System.out.println("Finished: " + Arrays.toString(Finish));
System.out.println("unFinished:" + unFinished);
System.out.println("preUnFinished:" + preUnFinished);
/*
* 如果发现程序执行完一周之后并没有减少 unFinished 那么表明找不到安全序列了
*/
}
if(unFinished == 0){
return true;
}
else
return false;
}