前言
银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。
数据结构
- 1)可利用资源向量Available
是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。 - 2)最大需求矩阵Max
这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。 - 3)分配矩阵Allocation
这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的 数目为K。 - 4)需求矩阵Need。
这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
Need[i,j]=Max[i,j]-Allocation[i,j]
算法原理
我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
- (1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
- (2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
- (3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
- (4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。
代码实现
#include <iostream>
using namespace std;
const int N = 5;///进程数目
const int M = 3;///资源类型数目
int AllResource[M]= {10,5,7}; ///各类类型资源矩阵
int Available[M];///可用的资源向量
int Request[M];///请求资源向量
int Max[N][N]=
{
///最大需求矩阵
{7,5,3},
{3,2,2},
{9,0,2},
{2,2,2},
{4,3,3}
};
int Allocation[N][M]=
{
///已分配资源矩阵
{0,1,0},
{2,0,0},
{3,0,2},
{2,1,1},
{0,0,2}
};
int Need[N][N];///需求矩阵
///展示当前所有资源情况
void show()
{
cout<<"--------------------------------------------------\n";
cout<<"当前各进程需要资源[Need]数量为:\n";
for(int i=0; i<M; i++)
{
cout<<"\t"<<"资源类型"<<i+1;
}
cout<<endl;
for(int i=0; i<N; i++)
{
cout<<"进程P"<<i<<":";
for(int j=0; j<M; j++)
{
cout<<"\t\t"<<Need[i][j];
}
cout<<endl;
}
cout<<"\n当前各进程已分配资源[Allocation]数量为:\n";
for(int i=0; i<M; i++)
{
cout<<"\t"<<"资源类型"<<i;
}
cout<<endl;
for(int i=0; i<N; i++)
{
cout<<"进程P"<<i<<":";
for(int j=0; j<M; j++)
{
cout<<"\t\t"<<Allocation[i][j];
}
cout<<endl;
}
cout<<"\n当前各类型资源的可利用[Available]数量为:\n";
cout<<"[";
for(int i=0; i<M; i++)
{
cout<<Available[i];
if(i!=M-1) cout<<",";
}
cout<<"]\n--------------------------------------------------\n";
}
///检验进程号是否合法
bool checkProcessId(int id)
{
if(id<0||id>=N) return false;
return true;
}
///请求资源非法对应的输出提示
void invalidRequestPrint(int id)
{
cout<<"进程P"<<id<<"请求资源数目不合理,请重新输入\n";
}
///资源更新
void update(int id)
{
for(int i=0; i<M; i++)
{
Available[i]-=Request[i];
Allocation[id][i]+=Request[i];
Need[id][i]-=Request[i];
}
}
///恢复资源更新
void rupdate(int id)
{
for(int i=0; i<M; i++)
{
Available[i]+=Request[i];
Allocation[id][i]-=Request[i];
Need[id][i]+=Request[i];
}
}
///安全性算法
bool safeCheck(int id)
{
int Work[M];
bool Finish[N];///Finish[i]=true表示进程号为i的请求安全
int safeSequence[N];///存储安全序列
int len=0;///记录安全序列的长度
for(int i=0; i<N; i++)
{
Finish[i]=false;
}
for(int j=0; j<M; j++)
{
Work[j]=Available[j];
while(checkProcessId(id))///进程号合法
{
if(!Finish[id]&&Need[id][j]<=Work[j])
{
Work[j]+=Allocation[id][j];
Finish[id]=true;
safeSequence[len++]=id;
id=0;
}
else id++;
}
for(int i=0; i<N; i++)
{
if(!Finish[i])
{
cout<<"\n请求资源失败!!!\n\n";
return false;
}
}
}
cout<<"\n请求资源成功!安全序列为:";
for(int i=0; i<len; i++)
{
cout<<safeSequence[i];
if(i!=len-1) cout<<"->";
}
cout<<"\n\n";
return true;
}
void banker()
{
char flag='y';
while(flag=='y'||flag=='Y')
{
int i=-1;
while(!checkProcessId(i))///进程号非法
{
cout<<"请输入合法的请求资源的进程号,否则再次输入:P";
cin>>i;
if(!checkProcessId(i))
{
cout<<"非法输入,请重新输入"<<endl;
}
}
for(int j=0; j<M; j++)
{
cout<<"进程P"<<i<<"请求资源类型"<<j<<"的个数为:";
cin>>Request[j];
if(Request[j]>Need[i][j])///请求资源大于进程所需资源
{
invalidRequestPrint(i);
flag='n';
break;
}
else
{
///请求资源数目合理
if(Request[j]>Available[j])///可利用的资源不够用
{
///请求的该资源类型的数目大于其可用资源数目
invalidRequestPrint(i);
flag='n';
break;
}
}
}
if(flag=='y'||flag=='Y')
{
update(i);///资源更新
if(!safeCheck(i))
{
///安全性算法,处于非安全状态
rupdate(i);///恢复资源更新以便输出
}
else
{
///确认分配请求资源后能否释放资源(即收回全部分配的资源)
bool flag=1;
for(int j=0; j<M; j++)
{
if(Need[i][j]!=0)
{
flag=0;
break;
}
}
if(flag)
{
for(int j=0; j<M; j++)
Available[j]+=Allocation[i][j];
}
}
}
show();
cout<<"按'y'或'Y'继续请求资源分配,否则退出:";
cin>>flag;
}
}
///系统资源的初始化
void init()
{
///初始化可利用资源向量
int tmp;
for(int j=0; j<M; j++)
{
tmp=AllResource[j];
for(int i=0; i<N; i++)
{
tmp-=Allocation[i][j];
Available[j]=max(tmp,0);
}
}
///初始化需求矩阵
for(int i=0; i<N; i++)
{
for(int j=0; j<M; j++)
{
Need[i][j]=Max[i][j]-Allocation[i][j];
}
}
}
int main()
{
init();
show();
banker();
return 0;
}