银行家算法的模拟与死锁避免
什么是死锁
死锁(Deadlock)是指在多进程系统中,每个进程都在等待其他进程释放所占用的资源,导致系统无法继续执行下去的一种状态。
死锁通常发生在多个进程同时竞争有限的资源,并且每个进程都在等待其他进程释放资源,同时又不释放自己所占有的资源,从而导致所有进程都无法继续执行下去,形成了死锁状态。
死锁产生的条件通常被称为死锁的必要条件,包括以下四个条件:
- 互斥条件(Mutual Exclusion):一个资源每次只能被一个进程占用,即在一段时间内只能由一个进程独占使用。
- 请求与保持条件(Hold and Wait):一个进程在申请新的资源的同时保持对已占有资源的不释放。
- 不剥夺条件(No Preemption):系统不能抢占进程所占用的资源,只能由进程自愿释放。
- 环路等待条件(Circular Wait):存在一个进程资源的循环链,使得每个进程都在等待下一个进程所占用的资源。
当这四个条件同时满足时,就有可能发生死锁。死锁的发生会导致系统停滞,进程无法继续执行,资源无法被有效利用,影响系统的可用性和性能。
为了避免死锁的发生,可以采取多种方法,包括资源分配策略、死锁检测与恢复、死锁预防和死锁避免等。其中,银行家算法就是一种用于死锁避免的资源分配算法,通过合理地控制资源分配,预防系统进入死锁状态。
什么是银行家算法
在多进程环境中,每个进程都需要申请一定数量的资源才能完成其任务。银行家算法通过对进程的资源请求进行检查和控制,保证系统能够分配资源而不会导致死锁的发生。
银行家算法基于以下假设:
- 每个进程在开始执行之前必须声明其最大需求资源量。
- 每个进程在执行过程中不会改变其最大需求资源量。
- 每个进程可以一次性申请并获得其所需的全部资源。
- 资源分配是有限制的,系统中的资源总量是固定的。
银行家算法的核心思想是,系统在分配资源之前先进行安全性检查,确保分配资源后系统仍然能够达到安全状态,即不会发生死锁。如果某个进程的资源请求导致系统进入不安全状态,那么该请求将被延迟,直到系统再次进入安全状态才能分配资源给该进程。
通过合理的资源分配和安全性检查,银行家算法可以有效地避免死锁问题,并确保系统的稳定性和可靠性。它在操作系统和并发编程中被广泛应用。
代码实现
思路: 对进程的资源请求进行合法性检查;若请求合法,则进行试分配。试探性分配后,调用安全性算法进行安全性检查。若安全,则满足该进程请求,分配资源;若不安全,则拒绝该进程申请,不分配资源,并恢复系统试分配前的资源状态。 代码:
#include<stdio.h>
#define MAXPROCESS 50
#define MAXRESOURCE 100
int AVAILABLE[MAXRESOURCE]; //可用资源数组
int MAX[MAXPROCESS][MAXRESOURCE]; //最大需求矩阵
int ALLOCATION[MAXPROCESS][MAXRESOURCE]; //分配矩阵
int NEED [MAXPROCESS][MAXRESOURCE];//需求矩阵
int REQUEST [MAXPROCESS][MAXRESOURCE]; //进程需要资源数
bool FINISH[MAXPROCESS]; //系统是否有足够的资源
int p[MAXPROCESS]; //记录序列
int m,n; //m个进程,n个资源
void Init(){
int i,j;
printf("-----------银行家算反模拟实现-----------\n");
printf("请输入进程的数目m:");
scanf("%d",&m);
printf("请输入资源的种类n:");
scanf("%d",&n);
printf("\n");
printf("请输入每个进程对资源数的最大需求,按照%d*%d矩阵输入\n",m,n);
// printf("%d,%d",&m,&n);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",&MAX[i][j]);
printf("请输入每个进程已分配的资源数,同样按照%d*%d矩阵输入\n",m,n);
for(i=0;i<m;i++)
{
for (j=0;j<n;j++)
{
scanf("%d",&ALLOCATION[i][j]);
NEED[i][j]=MAX[i][j]-ALLOCATION[i][j];
if(NEED[i][j]<0)
{
printf("进程%d的第%d个资源数超过其最大资源数,请输入\n",i+1,j+1);
j--;
continue;
}
}
}
printf("请输入各个资源现有的数目:\n");
for(i=0;i<n;i++)
{
scanf("%d",&AVAILABLE[i]);
}
printf("-----------------------------------------------/n");
}
bool Safe(){
int i,j,k,l=0;
int Work[MAXRESOURCE];
for(i=0;i<n;i++)
Work[i]=AVAILABLE[i];
for(i=0;i<m;i++)
FINISH[i]=false;//FINISH记录每个进程是否安全
for(i=0;i<m;i++)
{
if(FINISH[i]==true)
{
continue;
}
else
{
for(j=0;j<n;j++)
{
if(NEED[i][j]>Work[j])
{
break;
}
}
if(j==n)
{
FINISH[i]=true;
for(k=0;k<n;k++)
{
Work[k]+=ALLOCATION[i][k];//将Work赋值为 第i个进程各个已分配资源数+系统现有的对应资源数(因为当改进程全部资源数都满足时线程结束并将资源返还给系统)
}
p[l++]=i;
i=-1;
}
else
{
continue;
}
}
}
if(l==m)
{
printf("the system is safe.\n");
printf("the safe list is:\n");
for(i=0;i<1;i++)
{
printf("%d",p[i]);
if(i!=l-1)
{
printf("-->");
}
}
printf("\n");
return true;
}
else
{
printf("the system is not safe.\n");
return false;
}
}
void Bank()
{
int i,r;
int again;
while(1){
printf("请输入要申请资源的进程号r:\n");
scanf("%d",&r);
printf("请输入进程所请求的各资源的数量REQUEST:\n");
for(i=0;i<n;i++){
scanf("%d",REQUEST[r][i]);
}
for(i=0;i<n;i++)
{
if(r>m){
printf("您输入的请求数超过进程的需求量!请重新输入!\n");
break;
}
if(REQUEST[r][i]>NEED[r][i]&&REQUEST[r][i]>AVAILABLE[i]){
printf("您输入的请求数超过系统现有的资源数!请重新输入!\n");
break;
}
}
if(i<n) continue;
for(i=0;i<n;i++){
AVAILABLE[i]-=REQUEST[r][i];//系统可用资源减去申请了的
ALLOCATION[r][i]+=REQUEST[r][i];//线程被分配的资源加上已申请了的
NEED[r][i]-=REQUEST[r][i];//线程还需要的资源减去已申请得到的
}
if(Safe()){
printf("同意分配请求!\n");
}
else{
printf("您的请求被拒绝!\n");
for(i=0;i<n;i++){
AVAILABLE[i]+=REQUEST[r][i];
ALLOCATION[r][i]-=REQUEST[r][i];
NEED[r][i]+=REQUEST[r][i];
}
}
printf("您还想再次请求资源分配吗?如果是的话请按1,否则请按其他键\n");
scanf("%d",&again);
if(again==1) continue;
break;
}
}
int main(){
Init();
Safe(); //检验
Bank(); //资源分配的判断
return 0;
}
代码中的主要函数和变量包括:
Init()
函数用于初始化进程数目、资源种类、最大需求矩阵、已分配矩阵和可用资源数组等。Safe()
函数用于判断系统是否处于安全状态。它通过遍历进程和资源,检查系统中是否有足够的资源来满足每个进程的需求,如果找到一个安全序列,即进程可以按顺序执行而不发生死锁,就返回true
,否则返回false
。Bank()
函数用于进行资源分配判断。它首先接受用户输入的进程号和所请求的资源数量,然后检查请求是否超过进程的需求量和系统现有的资源数。如果请求合法,会尝试分配资源,并调用Safe()
函数来判断系统是否仍然处于安全状态。如果安全,即存在安全序列,会打印出同意分配请求的信息;如果不安全,会打印出请求被拒绝的信息,并将资源返还给系统。main()
函数是程序的入口,调用Init()
进行初始化,然后依次调用Safe()
和Bank()
来进行资源分配判断。
这段代码的目的是模拟银行家算法,判断系统在给定的资源分配情况下是否处于安全状态,以及根据用户的请求来决定是否分配资源。