死锁的起因,通常源于多个进程对资源的争夺,不仅对不可抢占资源进行争夺时会引起死锁,而且对可消耗资源进行争夺时,也会引起死锁。
在一组进程发生死锁的情况下,这组死锁进程中的每一个进程,都在等待另一个死锁进程占有的资源。如果一组进程中的每一个进程都在等待仅由该组进程汇总的其他进程才能引发的事件,那么该组进程是死锁的。
最有代表性的避免死锁的算法为银行家算法。
银行家算法:每一个新的进程进入系统时,必须申明在运行过程中,可能需要每种资源类型的最大单元数目,不应超过系统所拥有的资源总量,请求一组资源时,系统必须首先确定是否有足够的资源分配给进程,若有,再进一步计算在将这些资源分配给进程后,是否使进程处于不安全状态,如果不会,将资源分配给它。
输入:进程数、资源数,可利用资源向量Avaliable,最大需求矩阵Max,分配矩阵Allocation。
输出:首先判断系统是否处于安全状态,是的话输出Yes,否则输出No。
输入:进程Pi的序号,进程Pi的请求向量。
输出:系统是否分配资源给该进程。是的话输出Yes,反之输出No。
运行结果:
所需的数据结构:
//最大需求矩阵,n个进程对m类资源的最大需求
int Max[maxn][maxm]
//分配矩阵,系统中每一类资源当前分配给每个进程的资源数
int Allocation[maxn][maxm]
//需求矩阵,每一个进程尚需要的各类资源数目。
int Need[maxn][maxm]
//Available可利用资源向量,每一个元素代表可利用的资源数目
int Available[maxm]
//Request是进程p[i]的请求向量
int Request[maxm];
算法实现:
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int maxm = 100 + 5; //最大资源数
const int maxn = 100 + 5; //最大进程数
/*
银行家算法
每一个新的进程进入系统时,必须申明在运行过程中,可能需要每种资源类型的
最大单元数目,不应超过系统所拥有的资源总量,请求一组资源时,系统必须首
先确定是否有足够的资源分配给进程,若有,再进一步计算在将这些资源分配给
进程后,是否使进程处于不安全状态,如果不会,将资源分配给它。
*/
//最大需求矩阵,n个进程对m类资源的最大需求,分配矩阵,系统中每一类资源当前分配给每个进程的资源数
//需求矩阵,每一个进程尚需要的各类资源数目。
int Max[maxn][maxm], Allocation[maxn][maxm], Need[maxn][maxm];
//是否分配资源给i进程
bool isAllocate(int m, int i, int *Request, int *Available)
{
int j;
for(j = 0; j < m; j++)
{
if(Request[j] > Need[i][j]) //它需要的资源数已经超过它宣布的最大值
return false;
if(Request[j] > Available[j]) //尚无足够资源
return false;
}
return true;
}
//判断进程i是否满足条件
bool Find(int i, int m, int *Work)
{
int j;
for(j = 0; j < m; j++)
if(Need[i][j] > Work[j]) //无足够资源分配,不满足条件
return false;
return true;
}
//安全性算法:
bool Safe(int n, int m, int *Available)
{
bool finish[maxn]; //表示系统是否有足够的资源分配给进程。
int Work[maxm], i, j, cnt; //work表示系统可提供给进程继续运行所需的各资源数目
memset(finish, false ,sizeof(finish)); //初始全为false。
for(j = 0; j < m; j++) //初始Work=Available
Work[j] = Available[j];
cnt = n; //cnt为未分配资源的进程数
while(cnt)
{
for(i = 0; i < n; i++) //从进程集合中找到一个满足条件的进程
if(!finish[i] && Find(i, m, Work)) //有足够的资源分配
{
cnt--; //找到一个,cnt-1
finish[i] = true; //修改finish
for(j = 0; j < m; j++) //获得资源,释放分配的资源
Work[j] += Allocation[i][j];
break;
}
if(i == n) //找不到,不安全
break;
}
return (cnt == 0); //cnt为0,所有进程的finish=true都满足,系统处于安全状态,否则不安全
}
int main()
{
//Request是进程p[i]的请求向量
//Available可利用资源向量,每一个元素代表可利用的资源数目
int i, j, n, m, Request[maxm], int Available[maxm];
scanf("%d %d", &n, &m);
for(i = 0; i < m; i++)
scanf("%d", &Available[i]);
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
scanf("%d", &Max[i][j]);
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
scanf("%d", &Allocation[i][j]);
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
Need[i][j] = Max[i][j] - Allocation[i][j];
if(Safe(n, m, Available))
printf("Yes\n");
else
printf("No\n");
while(scanf("%d", &i) == 1)
{
for(j = 0; j < m; j++)
scanf("%d", &Request[j]);
if(isAllocate(m, i, Request, Available))
{
for(j = 0; j < m; j++) //分配资源后要修改数值
{
Available[j] -= Request[j];
Allocation[i][j] += Request[j];
Need[i][j] -= Request[j];
}
if(Safe(n, m, Available)) //执行安全性算法,安全则分配
printf("Yes\n");
else //否则恢复原来的资源分配状态
{
for(j = 0; j < m; j++)
{
Available[j] += Request[j];
Allocation[i][j] -= Request[j];
Need[i][j] += Request[j];
}
printf("No\n");
}
}
else
printf("No\n");
}
return 0;
}