大家好,又见面了,我是你们的朋友全栈君。
简述:银行家算法是一种可以避免死锁的方法
就是以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源就相当于用户向银行家贷款。
实现方法:
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(即当资源池中剩余的可利用资源 >= 线程还需要的资源时,就可以将可利用资源分配给此线程)
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(线程可以请求分配资源,但是请求的资源总数不能超过资源池中剩余的可利用资源)
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(当线程池中的资源暂时不满足当前的线程所需时,将此线程先暂时搁置,先将资源分配给能够满足的需求的其他线程,等到线程池中的资源足够满足先前搁置的线程时,在将资源分配给搁置的线程)
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金。
(当线程拿到所需要的所有资源,运行结束后,将自身所有的资源放回资源池中)
实例讲解
下图共有5个线程,4种资源,已经将线程池中的部分资源分配
分析过程:
资源池中剩余的可用资源量为1 6 2 2,现开始将可用资源量试分配给待运行的线程。
P0已经拥有了0 0 3 2,还需要0 0 1 2,将可以利用的资源量1 6 2 2分配给P0,资源池中就只剩下了1 6 1 0的资源,但P0拥有了0 0 4 4就开始运行,结束后释放自己的所有拥有的资源至资源池中,此时线程池中的总资源量为1 6 5 4,将P0的状态置为true。
P1已经拥有了1 0 0 0,还需要1 7 5 0,接下来本该将资源池中的资源分配给P1,但是经过比较,1 6 5 4 < 1 7 5 0,资源池中的资源不够分给P1,所以先将P1搁置,状态置为false
P2已经拥有了1 3 5 4,还需要2 3 5 6,接下来本该将资源池中的资源分配给P2,但是经过比较,1 6 5 4 < 2 3 5 6,资源池中的资源不够分给P2,所以先将P2搁置,状态置为false
P3已经拥有了0 3 3 2,还需要0 6 5 2,将可以利用的资源量1 6 5 4分配给P3,资源池中就只剩下了1 0 0 2的资源,但P3拥有了0 9 8 4就开始运行,结束后释放自己的所有拥有的资源至资源池中,此时线程池中的总资源量为1 9 8 6,将P3的状态置为true。
P4已经拥有了0 0 1 4,还需要0 6 5 6,将可以利用的资源量1 9 8 6分配给P4,资源池中就只剩下了1 3 3 0的资源,但P4拥有了0 6 6 10就开始运行,结束后释放自己的所有拥有的资源至资源池中,此时线程池中的总资源量为1 9 9 10,将P4的状态置为true。
然后回到搁置的线程处,重新试着分配。
第二个问题如下图:
代码实现:
实现过程中当部分线程资源得不到满足被暂时搁置后,要等到它的下一个线程状态置true时,从头开始再次进行试分配。
import java.util.Scanner;
public class Banker {
int available[] = new int[]{
3,3,2};//可得到的资源
int max[][] = new int[][]{
{
7,5,3},{
3,2,2},{
9,0,2},{
2,2,2},{
4,3,3}};//每个进程最大资源数
int allocation[][] = new int[][]{
{
0,1,0},{
2,0,0},{
3,0,2},{
2,1,1},{
0,0,2}};//每个进程目前拥有的资源数
int need[][] = new int[][]{
{
7,4,3},{
1,2,2},{
6,0,0},{
0,1,1},{
4,3,1}};//每个进程需要的资源数
void showData() {
//展示数据输出每个进程的相关数
System.out.println("进程号 Max All 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 m = 0;m<3;m++) System.out.print(max[i][m]+" ");
for(int m = 0;m<3;m++) System.out.print(allocation[i][m]+" ");
for(int m = 0;m<3;m++) System.out.print(need[i][m]+" ");
System.out.println();
}
}
boolean change(int inRequestNum,int inRequest[])//分配数据
{
int requestNum = inRequestNum;
int request[] = inRequest;
// for(int i=0;i<3;i++)System.out.println("修改前available"+available[i]);
if(!(request[0]<=need[requestNum][0]&&request[1]<=need[requestNum][1]&&request[2]<=need[requestNum][2]))
{
//request[0]<=need[requestNum][0]
//request[1]<=need[requestNum][1]
//request[2]<=need[requestNum][2]
//每一类请求资源小于当前线程need的资源数
System.out.println("请求的资源数超过了所需要的最大值,分配错误");
return false;
}
if((request[0]<=available[0]&&request[1]<=available[1]&&request[2]<=available[2])==false)
{
//当前线程的每一类请求资源小于等于资源池对应资源的数量
System.out.println("尚无足够资源分配,必须等待");
return false;
}
for(int i = 0;i<3;i++)//试分配数据给请求的线程
{
available[i] = available[i]-request[i];
//资源池的每类资源减去每类请求资源数量
allocation[requestNum][i] = allocation[requestNum][i] + request[i];
//当前线程allocation中每类资源加上每类资源请求数量
need[requestNum][i] = need[requestNum][i] - request[i];
//当前线程need中每类资源数量减去每类资源的请求数量
}
// for(int i=0;i<3;i++)System.out.println("修改后available"+available[i]);
boolean flag = checkSafe(available[0],available[1],available[2]);//进行安全性检查并返回是否安全
// System.out.println("安全性检查后"+flag);
if(flag==true)
{
System.out.println("能够安全分配");
return true;
}
else//不能通过安全性检查 恢复到未分配前的数据
{
System.out.println("不能够安全分配");
for(int i = 0;i<3;i++)
{
available[i] = available[i]+request[i];
allocation[requestNum][i] = allocation[requestNum][i] - request[i];
need[requestNum][i] = need[requestNum][i] + request[i];
}
return false;
}
}
boolean checkSafe(int a,int b,int c)//安全性检查
{
int work[] = new int[3];
work[0] = a;
work[1] = b;
work[2] = c;
int i=0;
boolean finish[] = new boolean[5];
while(i<5)//寻找一个能够满足的认为完成后才去执行下一进程
{
if(finish[i]==false&&need[i][0]<=work[0]&&need[i][1]<=work[1]&&need[i][2]<=work[2])
{
//找到满足的修改work值,然后i=0,重新从开始的为分配的中寻找
System.out.println("分配成功的是"+i);
for(int m = 0;m<3;m++)
work[m] =work[m] + allocation[i][m];
finish[i] = true;
i=0;
}
else//如果没有找到直接i++
i++;
}
for(i=0;i<5;i++)//通过finish数组判断是否都可以分配
{
if(finish[i]==false)
return false;
}
return true;
}
public static void main(String[] args)
{
Banker bank = new Banker();
bank.showData();
//请求线程资源存放的数组
int request[] =new int[3];
int requestNum;
String source[] = new String[]{
"A","B","C"};
Scanner s = new Scanner(System.in);
String choice = new String();
while(true)//循环进行分配
{
System.out.println("请输入要请求的进程号(0--4):");
requestNum = s.nextInt();
System.out.print("请输入请求的资源数目");
for(int i = 0;i<3;i++)
{
System.out.println(source[i]+"资源的数目:");
request[i] = s.nextInt();
}
bank.change(requestNum, request);
System.out.println("是否再请求分配(y/n)");
choice = s.next();
if(choice.equals("n"))
break;
}
}
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/163227.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...