首先了解一波产生死锁的必要条件
1).互斥条件:进程对所分配到的资源进行排它性使用,即在一段时间内,某资源只能被一个进程占用。如果此时还有其他进程请求该资源,则请求资源只能等待,直至占有该资源的进程用毕释放.
2).请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已经被其他进程占有,此时请求进程被保持,但对自己所获得的资源又保持不放.
3).不可抢占条件:进程已获得的资源在未使用完之前不可被抢占,只能在使用完成后自己释放.
4).环路等待:在发生死锁时,必然存在一个进程,资源的循环链.
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。
注:存在安全序列则系统是安全的,如果不存在则系统不安全,但不安全状态不一定引起死锁。
原理过程:
系统给当前进程分配资源时,先检查是否安全:在满足当前的进程X资源申请后,是否还能有足够的资源去满足下一个距最大资源需求最近的进程(如某进程最大需要5个单位资源,已拥有1个,还尚需4个),若可以满足,则继续检查下一个距最大资源需求最近的进程,若均能满足所有进程,则表示为安全,可以允许给当前进程X分配其所需的资源申请,否则让该进程X进入等待。
(注:检查过程中,每拟满足一个进程,则进行下个检查时,当前可用资源为回收上一个进程资源的总值,每满足一个进程表示此进程已结束,资源可回收。)
算法过程:
1).银行家算法中的数据结构
(1).可利用资源向量
(2).最大需求矩阵
(3).分配矩阵
(4).需求矩阵
2)对于当前需要申请资源的进程Pi X
(1) 检查if( Request[ i ][ j ]<=Need[ i ][ j ] ) goto (2)
else error(“进程 i 对资源的申请量大于其说明的最大值 ”);
(2) 检查 if ( Request[ i ][ j ]<=Available[ j ] ) goto (3)
else wait() ; /*注意是等待!即在对后续进程的需求资源判断中,若出现不符合的则安全检查结束,当前进程进入等待*/
(3) 系统试探地把资源分给Pi 并修改各项属性值 (具体是否成立,则根据安全检查的结果)
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 ]
具体的算法实现:
#include <iostream>#include <string.h>
#include <string>
using namespace std;
const int maxnsource = 100;
const int maxnprocess = 50;
int available[maxnsource];//可以使用的资源。int max[maxnprocess][maxnprocess];//最大需求矩阵。
int allocation[maxnprocess][maxnprocess];//已经分配的矩阵。
int need[maxnprocess][maxnprocess];//还需要的矩阵。
int requestsource[maxnprocess][maxnprocess];//进程请求的矩阵。
int finish[maxnprocess];//进程是否能得到足够的资源使其结束。
int n, m;
int i, j;
int p[maxnsource];//记录进程号
int safe()//判断是否为安全的
{
int cnt = 0;
int flag = 0;
int temp[maxnsource];
for (i = 0; i < n; i++)
temp[i] = available[i];
for (i = 0; i < m; i++)
{
if (finish[i] == 0)
{
for (j = 0; j < n; j++)
{
if (need[i][j] > temp[j])
break;
}
if (j == n)
{
finish[i] = 1;
for (int k = 0; k < n; k++)
temp[k] += allocation[i][k];
p[cnt++] = i;
i = -1;//这里不是0,重置之后i++会变为1,就错了。
}
else
continue;
if (cnt == m)
{
cout << "系统是安全的" << endl;
cout << "安全序列:" << endl;
for (i = 0; i<cnt; i++)
{
cout << p[i];
if (i != cnt - 1)
{
cout << "-->";
}
}
cout << "" << endl;
return 1;
}
}
}
cout << "系统是不安全的" << endl;
return 0;
}
void bank()//银行家算法
{
int cur;
while (1)
{
cout << "输入要申请资源的进程号" << endl;
cin >> cur;
cout<< "输入进程所请求的各资源的数量" << endl;
for (int i = 0; i < n; i++)
cin >> requestsource[cur][i];
for (int i = 0; i < n; i++)
{
if (requestsource[cur][i] > need[cur][i])
{
cout << "输入的请求数超过进程的需求量!请重新输入!" << endl;
continue;
}
if (requestsource[cur][i] > available[i])
{
cout << "输入的请求数超过系统有的资源数!请重新输入!" << endl;
continue;
}
}
for (int i = 0; i < n; i++)
{
available[i] -= requestsource[cur][i];
allocation[cur][i] += requestsource[cur][i];
need[cur][i] -= requestsource[cur][i];
}
for (int i = 0; i < m; i++)
finish[i] = 0;
if (safe())
{
cout << "同意分配请求!" << endl;
}
else
{
cout << "您的请求被拒绝!" << endl;
for (int i = 0; i < n; i++)
{
available[i] += requestsource[cur][i];
allocation[cur][i] -= requestsource[cur][i];
need[cur][i] += requestsource[cur][i];
}
for (int i = 0; i < m; i++)
finish[i] = 0;
string s;
cout << "是否还想再次请求分配吗?如果想,请输入YES" << endl;
cin >> s;
if (s == "YES")
continue;
else
break;
}
}
}
int main()
{
memset(finish, 0, sizeof(finish));
cout << "输入进程的数量:";
cin >> m;
cout << "输入资源的种类:";
cin >> n;
cout << "输入每个进程最多所需要的资源数:";
for (i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> max[i][j];
cout << "输入每个进程已经分配的资源数:";
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
cin >> allocation[i][j];
need[i][j] = max[i][j] - allocation[i][j];
if (need[i][j] < 0)
{
cout << "输入的第" << i + 1 << "个进程所拥有的第" << j + 1 << "个资源数 错误,请重新输入:" << endl;
j--;
continue;
}
}
}
cout << "输入各资源现有的资源数:";
for (i = 0; i < n; i++)
cin >> available[i];
/*for (i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
cout << max[i][j] << " ";
cout << endl;
}
for (i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
cout << allocation[i][j] << " ";
cout << endl;
}
for (i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
cout << need[i][j] << " ";
cout << endl;
}*/
safe();
bank();
return 0;
}