银行家算法思想:
1.银行家算法中的数据结构:
(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]
2.系统所执行的安全性算法可描述如下:
(1) 设置两个向量:
①工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work:=Available。
②Finish,它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]:=false;当有足够资源分配给进程时,再令Finish[i]:=true。
(2) 从进程集合中找到一个能满足下述条件的进程:
① Finish[i]=false;
② Need[i,j]≤Work[j];若找到,执行步骤(3),否则,执行步骤(4)。
(3) 当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Finish[i]:=true;
go to step (2);
3.申请资源:
设Request i是进程Pi的请求向量,如果Request i[j]=K,表示进程P i需要K个R j类型的资源。当P i发出资源请求后,系统按下述步骤进行检查:
(1) 如果Request i[j]<=Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。
(2) 如果Request i[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,Pi须等待。
(3) 系统试探着把资源分配给进程P i,并修改下面数据结构中的数值:
Available[j]:= Available[j]-Request i[j];
Allocation[i,j]:= Allocation[i,j]+Request i[j];
Need[i,j]:= Need[i,j]-Request i[j];
(4) 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
一开始我是按照老师给的PPT上的具体操作过程写的,但是可能是我当时对银行家算法的具体实现步骤和其中的安全性检查算法不太了解,认为只有在申请资源之后才需要安全性检查,而且当时写的安全性检查的代码中对循环操作也有错,导致运行错误。
然后我上网找了下讲解银行家算法的视频,跟着视频里的步骤来,算是懂了一些,然后知道了之前出现错误的部分原因,我理解的具体操作如下:
1.根据输入的Max数组、Allocation数组以及Available数组,通过运算得到Need数组、更新了的Available数组;
2.然后进行安全性检查,判断此时程序是否安全;
3.输入申请的资源,然后预分配之后,进行安全性检查,安全则分配,不安全则取消分配。(其中申请资源可能会有多次)
而安全性检查算法是我觉得最绕的:
首先要遍历一下所有的进程,找到所需资源比Available数组中资源数小的进程,然后再实施资源预分配,然后再用Finish数组存储分配结果,最后如果每个进程都是true,则安全。
这几句话虽然说着感觉很好懂,但是到我具体操作的时候,我就一直觉得这个循环很绕,很难理清楚,然后参照了一下网上的关于这部分的代码在算是弄懂了一些。
代码如下:
#include <iostream>
using namespace std;
const int MAXN = 105;
int Available[MAXN];//可利用资源向量
int Max[MAXN][MAXN];//最大需求矩阵
int Allocation[MAXN][MAXN];//分配矩阵
int Need[MAXN][MAXN];//需求矩阵
int Request[MAXN][MAXN];//进程的请求矩阵
int Work[MAXN];//工作向量
bool Finish[MAXN];//表示系统是否有足够的资源分配给进程,使之运行完成
int m, n;//m为可用资源个数,n为进程个数
int *safe_array = new int[n];//存储安全序列
void init()//初始化
{
cout << "请输入可用资源个数和进程个数:" << endl;
cin >> m >> n;
cout << "数组Available[i]表示第i类资源的个数,请依次输入:" << endl;
for (int i = 1; i <= m; i++)
{
//cout << "Available[" << i << "]= ";
cin >> Available[i];
}
cout << "数组Max[i][j]表示进程i需要第j类资源的最大数目,请依次输入:" << endl;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
//cout << "Max[" << i << "][" << j << "]= ";
cin >> Max[i][j];
}
cout << "数组Allocation[i][j]表示进程i当前已经分得第j类资源的数目,请依次输入:" << endl;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
//cout << "Allocation[" << i << "][" << j << "]= ";
cin >> Allocation[i][j];
Need[i][j] = Max[i][j] - Allocation[i][j];
Available[j] -= Allocation[i][j];//更新当前可用资源数组
}
cout << "数组Need[i][j]表示进程i需要j类型的资源的数目,请依次输入:" << endl;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
//cout << "Need[" << i << "][" << j << "]= ";
cin >> Need[i][j];
}
}
bool security()//判断系统是否安全
{
for (int i = 1; i <= m; i++)//资源数m循环
Work[i] = Available[i];//RIGHT
for (int j = 1; j <= n; j++)//进程nFinish数组初始化
Finish[j] = false;//必须在每次安全性检查之前初始化Finish数组 !!!!
int p = 0;//p是安全序列safe_array数组的下标
//安全序列检查的第一种写法
for (int i = 1; i <= n; i++)//进程循环
{
int cnt = 0;//记录i进程的满足条件的资源数(之前的代码中忽略了要每个进程的所有的所需资源都要满足条件这个问题)
for (int j = 1; j <= m; j++)//资源循环
{
if (!Finish[i] && Need[i][j] <= Work[j])//满足条件
cnt++;
if (cnt == m)//进程i的所需资源全部满足条件,则分配资源
{
for (int k = 1; k <= m; k++)
Work[k] += Allocation[i][k];
Finish[i] = true;
safe_array[p++] = i;
i = 0;//检查前面是否有满足情况的进程(很重要)
//与PPT中的执行顺序不太一样,PPT中是先找剩下的中间最小的先看是否满足条件,而这里是先找进程序号在前面的进程是否满足条件
}
}
}
for (int i = 1; i <= n; i++)//看是否每个进程的Finish数组是否为true,是否有安全序列
if (!Finish[i])
{
cout << "当前系统不安全!" << endl;
return false;
}
cout << "当前系统安全!" << endl;
cout << "安全序列为:" << endl;
for (int i = 0; i < n - 1; i++)
cout << "P" << safe_array[i] - 1 << "->";
cout << "P" << safe_array[n - 1] - 1 << endl;
return true;
//安全序列检查的第二种写法
//for (int i = 1; i <= n; i++)//进程循环遍历
//{
// bool flag1 = false;//标记是否还存在Finish[i]=false&&Need[i][j]<=Work[j]
// for (int j = 1; j <= n; j++)//进程循环遍历
// {
// if (Finish[j])
// continue;
// bool flag2 = true;//标记该进程是否满足Finish[i]=false&&Need[i][j]<=Work[j]
// for (int k = 1; k <= m; k++)//资源循环遍历
// {
// if (Need[j][k] > Work[k])
// flag2 = false;
// }
// if (flag2)//满足条件的进程加入安全序列中
// {
// flag1 = Finish[j] = true;
// safe_array[p++] = j - 1;
// for (int k = 1; k <= m; k++)//资源循环遍历
// {
// Work[k] += Allocation[j][k];
// }
// break;
// }
// }
//}
}
void m_request()//接受请求
{
int i;
bool flag1 = false;//flag1标记申请的资源数是否超过它所需要的资源数量
bool flag2 = false;//flag2标记申请的资源数是否超过了当前所能使用的资源数量
cout << "请输入申请资源的进程号:" << endl;
cin >> i;
cout << "请依次输入申请的资源数目:" << endl;
int k = i + 1;
for (int j = 1; j <= m; j++)
{
cin >> Request[k][j];
if (Request[k][j] > Need[k][j])//PPT上有误
flag1 = true;
if (Request[k][j] > Available[j])
flag2 = true;
}
if (flag1 || flag2)//判断并输出不能执行的原因
{
if (flag1)
cout << "WRONG 申请的资源数量超过了该进程所需要的资源数量!" << endl;
else if (flag2)
cout << "WRONG 申请的资源数量超过了当前所能使用的资源数量!进程" << i << "进入等待状态!" << endl;
else
cout << "WRONG 申请的资源数量超过了该进程所需要的资源数量或者当前所能使用的资源数量!进程" << i << "进入等待状态!" << endl;
}
else//尝试分配资源并判断
{
for (int j = 1; j <= m; j++)//分配资源
{
Available[j] -= Request[k][j];
Allocation[k][j] += Request[k][j];
Need[k][j] -= Request[k][j];
}
if (security())//分配不成功
cout << "分配资源成功!" << endl;
else
{
cout << "分配资源失败,进程" << i << "进入等待状态!" << endl;
for (int j = 1; j <= m; j++)//复原
{
Available[j] += Request[k][j];
Allocation[k][j] -= Request[k][j];
Need[k][j] += Request[k][j];
}
}
}
}
void main()
{
init();
if (security())
{
int a;//存储操作编号
cout << "请输入操作序号,查询当前资源分配情况(1),请求资源(2),结束此次操作(3):" << endl;
cin >> a;
switch (a)
{
case 1:
break;
case 2:
{
int r_n;//申请资源次数
cout << "请输入申请资源次数" << endl;
cin >> r_n;
while (r_n--)
m_request();
break;
}
case 3:
default:
cout << "此次操作结束!" << endl;
break;
}
}
else
{
cout << "本次操作无效" << endl;
}
}
运行结果:
参考:银行家算法实现