银行家算法的模拟与死锁避免

什么是死锁

死锁(Deadlock)是指在多进程系统中,每个进程都在等待其他进程释放所占用的资源,导致系统无法继续执行下去的一种状态。

死锁通常发生在多个进程同时竞争有限的资源,并且每个进程都在等待其他进程释放资源,同时又不释放自己所占有的资源,从而导致所有进程都无法继续执行下去,形成了死锁状态。

死锁产生的条件通常被称为死锁的必要条件,包括以下四个条件:

  1. 互斥条件(Mutual Exclusion):一个资源每次只能被一个进程占用,即在一段时间内只能由一个进程独占使用。
  2. 请求与保持条件(Hold and Wait):一个进程在申请新的资源的同时保持对已占有资源的不释放。
  3. 不剥夺条件(No Preemption):系统不能抢占进程所占用的资源,只能由进程自愿释放。
  4. 环路等待条件(Circular Wait):存在一个进程资源的循环链,使得每个进程都在等待下一个进程所占用的资源。

当这四个条件同时满足时,就有可能发生死锁。死锁的发生会导致系统停滞,进程无法继续执行,资源无法被有效利用,影响系统的可用性和性能。

为了避免死锁的发生,可以采取多种方法,包括资源分配策略、死锁检测与恢复、死锁预防和死锁避免等。其中,银行家算法就是一种用于死锁避免的资源分配算法,通过合理地控制资源分配,预防系统进入死锁状态。

什么是银行家算法

在多进程环境中,每个进程都需要申请一定数量的资源才能完成其任务。银行家算法通过对进程的资源请求进行检查和控制,保证系统能够分配资源而不会导致死锁的发生。

银行家算法基于以下假设:

  1. 每个进程在开始执行之前必须声明其最大需求资源量。
  2. 每个进程在执行过程中不会改变其最大需求资源量。
  3. 每个进程可以一次性申请并获得其所需的全部资源。
  4. 资源分配是有限制的,系统中的资源总量是固定的。

银行家算法的核心思想是,系统在分配资源之前先进行安全性检查,确保分配资源后系统仍然能够达到安全状态,即不会发生死锁。如果某个进程的资源请求导致系统进入不安全状态,那么该请求将被延迟,直到系统再次进入安全状态才能分配资源给该进程。

通过合理的资源分配和安全性检查,银行家算法可以有效地避免死锁问题,并确保系统的稳定性和可靠性。它在操作系统和并发编程中被广泛应用。

代码实现

思路:
对进程的资源请求进行合法性检查;若请求合法,则进行试分配。试探性分配后,调用安全性算法进行安全性检查。若安全,则满足该进程请求,分配资源;若不安全,则拒绝该进程申请,不分配资源,并恢复系统试分配前的资源状态。
代码:

#include
#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()来进行资源分配判断。

这段代码的目的是模拟银行家算法,判断系统在给定的资源分配情况下是否处于安全状态,以及根据用户的请求来决定是否分配资源。

你可能感兴趣的:(笔记,算法,c++)