避免死锁的银行家算法

死锁的定义>

   如果一组进程中的每一个进程都在等待仅由该组进程中的其他进程才能引发的事件,那仫该组进程就是死锁的.

产生死锁的必要条件>

    1).互斥条件:进程对所分配到的资源进行排它性使用,即在一段时间内,某资源只能被一个进程占用。如果此时还有其他进程请求该资源,则请求资源只能等待,直至占有该资源的进程用毕释放.

    2).请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已经被其他进程占有,此时请求进程被保持,但对自己所获得的资源又保持不放.

    3).不可抢占条件:进程已获得的资源在未使用完之前不可被抢占,只能在使用完成后自己释放.

    4).环路等待:在发生死锁时,必然存在一个进程,资源的循环链.

   

 死锁产生的原因>

   1).竞争可重用不可抢占式的资源

   2).竞争可消耗资源

   3).进程推进顺序不当.

   可重用性资源:可供重复使用多次的资源.

   不可抢占性资源:一旦系统把某资源分配给该进程后,就不能将它强行收回,只能在进程使用完后自动释放.

   可消耗资源:又叫临时性资源,它是在进程运行期间,由进程动态的创建和消耗的.

 利用银行家算法解决死锁>

1).银行家算法中的数据结构

      (1).可利用资源向量Available

      (2).最大需求矩阵Max

      (3).分配矩阵Allocation

      (4).需求矩阵Need

2).银行家算法

Request请求向量,

     (1).如果Request[i] <= Need[i][j]转下步,否则它所需要的资源数已超过它所需要的最大值

     (2).如果Request[i] <= Available[i][j]转下步,否则尚无足够资源,进程需等待  

     (3).系统试分配给进程p,并修改Available,Allocation和Need

                   Available[j] -= Request[j]

                   Allocation[i][j] += Request[j]

                   Need[i][j] -= Request[j]

     (4)系统执行安全性算法,检查此次资源分配后系统是否处于安全状态.若安全,才正式分配;否则恢复原来的分配状态,让该进程等待

3).安全性算法

    (1).设置两个向量,工作向量Work,在执行安全性算法开始时 Work=Available;Finish:表示有足够的资源分配给进程,使之运行完成,Finish[i]=false;当有足够资源分配给进程时,再另Finish[i]=false

   (2).从进程集合中找到一个满足该条件的进程:

           Finish[i]=false

           Need[i][j] <= Work[j]

   (3).当进程获得资源后,可顺利执行,并修改Work向量和Finsh向量

          Work[i] += Allocation[i][j]

          Finish[i]=true

   (4).如果所有进程的Finish[i]=true说明系统处于安全状态,否则系统处于不安全状态.

   在实现这份代码的时候陷入了一个误区那就是当你找到了一个安全序列之后,它查找过的Finish必定会被修改为true,而Finish这个数组又是在全局定义的,所以只要找到一次正确的安全序列这个Finish所找到的位就会被置为true会一直出现找到安全序列的,所以在找到安全序列之后一定要将Finish重新赋初值false,这个问题让我排错了半天,在定义变量的时候最好不要定义为全局的。。。

    

const int MAXPROCESS=100;
const int MAXRESOURCE=100; 

int Available[MAXRESOURCE];         //可用资源向量  
int Max[MAXPROCESS][MAXRESOURCE];   //最大需求矩阵  
int Allocation[MAXPROCESS][MAXRESOURCE];  //分配矩阵  
int Need[MAXPROCESS][MAXRESOURCE];        //需求矩阵  

int Request[MAXRESOURCE];      //请求向量  
 
int Work[MAXRESOURCE];         //工作向量  
bool Finish[MAXPROCESS]; 
int SafeSeries[MAXPROCESS];    //安全序列  

int n;   //进程数  
int m;   //资源数  

void Init()  
{  
	cout<<"请输入进程总数>";  
	cin>>n;
	cout<<"请输入资源种类数>";  
	cin>>m;
	int i,j;  
	printf("请输入%d类资源的当前可利用资源数目>\n",m);
	for( i = 0; i < m; ++i )  
	{  
		cin >> Available[i];  
	}  
	printf("最大需求矩阵(%d*%d输入)>\n",n,m);
	for( i = 0; i < n; ++i )  
	{  
		for( j = 0; j < m; ++j )  
		{  
			cin >> Max[i][j];  
		}  
	}  
	printf("分配矩阵(%d*%d输入)>\n",n,m); 
	for( i = 0; i < n; ++i )  
	{  
		for( j = 0; j < m; ++j )  
		{  
			cin >> Allocation[i][j];  
		}  
	}  
	printf("需求矩阵(%d*%d输入)\n",n,m); 
	for( i = 0; i < n; ++i )  
	{  
		for( j = 0; j < m; ++j )  
		{  
			cin >> Need[i][j];  
		}  
	}  
}  

bool IsSafe()  
{  
	int i=0;
	for (i=0;i<n;++i)
	{
		if(Finish[i] == true)
			continue;
		else
			break;
	}
	if(i == n)
		return true;    //安全
	else
		return false;   //不安全
}   

bool Select(int &tmp,int tmpNeed[][MAXRESOURCE])  
{  
	//选择一个Finish[i]=false,Need[i]<=Work[i] 
	int j=0; 
	for (int i=0;i<n;++i)
	{
		if(Finish[i])
			continue;
		for (j=0;j<m;++j)
		{
			if(tmpNeed[i][j] > Work[j])
				break;
		}
		if(j == m)
		{
			tmp=i;
			return true;
		}
	}
	return false;
}  

bool Safe(int *tmpAvail,int tmpAlloc[][MAXRESOURCE],int tmpNeed[][MAXRESOURCE])  
{  
	for(int i = 0; i < n; ++i)  
	{  
		Finish[i] = false;  
	}  
	for (int j = 0; j < m; ++j)  
	{  
		Work[j] = tmpAvail[j];  
	}  
	int tmp=0;  
	int index = 0;  
	while(Select(tmp,tmpNeed))  
	{  
		Finish[tmp] = true;  
		for (int k = 0; k < m; ++k)  
		{  
			Work[k] += tmpAlloc[tmp][k];  
		}  
		SafeSeries[index++] = tmp;
	}  
	if(IsSafe())  
		return true;    //安全
	else
		return false;   //不安全
}   

void Display()
{
	int i=0;
	int j=0;
	cout<<"当前可利用的资源数目"<<endl;
	for(i = 0; i < m; ++i)  
	{  
		cout << Available[i]<<" ";  
	}  
	cout<<endl;
	cout<<"最大需求矩阵"<<endl;
	for(i = 0; i < n; ++i )  
	{  
		for( j = 0; j < m; ++j)  
		{  
			cout<<Max[i][j]<<" ";
		}  
		cout<<endl;
	}  
	cout<<"分配矩阵"<<endl;
	for( i = 0; i < n; ++i )  
	{  
		for( j = 0; j < m; ++j )  
		{  
			cout<<Allocation[i][j]<<" "; 
		}  
		cout<<endl;
	}  
	cout<<"需求矩阵"<<endl;
	for( i = 0; i < n; ++i )  
	{  
		for( j = 0; j < m; ++j )  
		{  
			cout<<Need[i][j]<<" ";
		}  
		cout<<endl;
	} 
}

void BankA()
{
	int i=0;
	int index=0;
	cout<<"请输入请求资源的进程下标>";
	cin>>index;
	assert(index < n && index >= 0);
	cout<<"请输入当前的请求资源>"<<endl;
	for (i=0;i<m;++i)
	{
		cin>>Request[i];
	}
	for (i=0;i<m;++i)
	{
		if(Request[i] <= Need[index][i])
		{
			continue;
		}
		else
		{
			cout<<"第一次试分配失败"<<endl;
			break;
		}
	}
	if(i < 3)   //如果第一次试分配失败则不执行后面的语句
	{
		return ;
	}
	for(i=0;i<m;++i)
	{
		if(Request[i] <= Available[i])
		{
			continue;
		}
		else
		{
			cout<<"第二次试分配失败"<<endl;
			break;
		}
	}
	if(i < 3)     //如果第二次试分配失败则不同执行后面的语句
	{
		return ;
	}
	//开始试分配
	int tmpAvail[MAXRESOURCE]={0};
	int tmpAlloc[MAXPROCESS][MAXRESOURCE]={0};
	int tmpNeed[MAXPROCESS][MAXRESOURCE]={0};
	memmove(tmpAvail,Available,sizeof(int)*MAXRESOURCE);
	memmove(tmpAlloc,Allocation,sizeof(int)*MAXPROCESS*MAXRESOURCE);
	memmove(tmpNeed,Need,sizeof(int)*MAXPROCESS*MAXRESOURCE);
	for (int i=0;i<m;++i)
	{
		tmpAvail[i] -= Request[i];
		tmpAlloc[index][i] += Request[i];
		tmpNeed[index][i] -= Request[i];
	}
	//开始执行安全性算法
	bool ret=Safe(tmpAvail,tmpAlloc,tmpNeed);
	if(ret == true)
	{
		//如果试分配成功则更新Available,Allocation,Allocation的状态
		memmove(Available,tmpAvail,sizeof(int)*MAXRESOURCE);
		memmove(Allocation,tmpAlloc,sizeof(int)*MAXPROCESS*MAXRESOURCE);
		memmove(Need,tmpNeed,sizeof(int)*MAXPROCESS*MAXRESOURCE);
		cout<<"进程p"<<index<<"请求资源允许"<<endl;
	}
	else
	{
		//只要试分配失败则将Finish置为false
		for(int i = 0; i < n; ++i)  
		{  
			Finish[i] = false;  
		}  
		cout<<"第三次试分配失败"<<endl;
	}
}

void Menu()
{
	cout<<"*************银行家算法*************"<<endl;
	cout<<"**********1.测试安全性代码**********"<<endl;
	cout<<"**********2.测试银行家算法**********"<<endl;
	cout<<"**********3.初始化******************"<<endl;
	cout<<"**********4.打印矩阵****************"<<endl;
	cout<<"**********0.退出********************"<<endl;
}


   test.cpp

   

void testBank()
{
	int index=0;
	int flag=1;
	while (flag)
	{
		Menu();
		cout<<"请输入您的选择"<<endl;
		cin>>index;
		switch(index)
		{
		case 1:
			Safe(Available,Allocation,Need);
			if(IsSafe())  
			{  
				cout<<"该时刻是安全的,安全序列为>"; 
				for (int i = 0; i < n ; ++i)  
				{  
					printf("p%d->",SafeSeries[i]);
				}  
				cout<<"end"<<endl;
				//分配成功将Finish的值置为false
				for(int i = 0; i < n; ++i)  
				{  
					Finish[i] = false;  
				}  
			}  
			else  
			{  
				cout<<"该时刻是不安全的"<<endl;
			} 
			break;
		case 2:
			BankA();
			if(IsSafe())  
			{  
				cout<<"安全序列为>"; 
				for (int i = 0; i < n ; ++i)  
				{  
					printf("p%d->",SafeSeries[i]);
				}  
				cout<<"end"<<endl;
				//分配成功将Finish的值置为false
				for(int i = 0; i < n; ++i)  
				{  
					Finish[i] = false;  
				}  
			}  
			else  
			{  
				cout<<"进程请求资源不被允许"<<endl;
			} 
			break;
		case 3:
			Init();
			break;
		case 4:
			Display();
			break;
		case 0:
			flag=0;
			break;
		default:
			cout<<"您的输入错误,请重新输入"<<endl;
			break;
		}
	}
}

  
 

 

  虽然搞了一下午写完整了这个银行家算法,整体效果还算满意,但是作为网络工程专业的学生今年虽然学了java的GUI但是仍然不会用图形用户界面(GUI)来对这个程序做一个界面出来,感觉好悲催哭,以后一定努力学习这方面的知识

  实现效果

   

     

     

    

    

     

   。。。

  • 17
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在C语言中实现避免死锁银行家算法可以通过以下步骤来实现: 1. 定义资源的最大需求量、已分配数量和可用资源数量。 ```c int max[NUMBER_OF_CUSTOMERS][NUMBER_OF_RESOURCES]; int allocation[NUMBER_OF_CUSTOMERS][NUMBER_OF_RESOURCES]; int available[NUMBER_OF_RESOURCES]; ``` 2. 实现安全性检查函数,判断当前状态是否安全。 ```c int isSafeState(int customer_id, int request[]) { // 模拟分配资源给该进程 for (int i = 0; i < NUMBER_OF_RESOURCES; i++) { available[i] -= request[i]; allocation[customer_id][i] += request[i]; } // 执行安全性检查 int work[NUMBER_OF_RESOURCES]; bool finish[NUMBER_OF_CUSTOMERS]; for (int i = 0; i < NUMBER_OF_RESOURCES; i++) { work[i] = available[i]; } memset(finish, false, sizeof(finish)); int count = 0; while (count < NUMBER_OF_CUSTOMERS) { bool found = false; for (int i = 0; i < NUMBER_OF_CUSTOMERS; i++) { if (!finish[i]) { bool canFinish = true; for (int j = 0; j < NUMBER_OF_RESOURCES; j++) { if (max[i][j] - allocation[i][j] > work[j]) { canFinish = false; break; } } if (canFinish) { // 进程可以完成,释放资源 finish[i] = true; for (int j = 0; j < NUMBER_OF_RESOURCES; j++) { work[j] += allocation[i][j]; } found = true; count++; } } } if (!found) { // 没有找到可完成的进程 break; } } // 恢复分配资源前的状态 for (int i = 0; i < NUMBER_OF_RESOURCES; i++) { available[i] += request[i]; allocation[customer_id][i] -= request[i]; } return count == NUMBER_OF_CUSTOMERS; } ``` 3. 实现资源请求函数,处理进程对资源的请求。 ```c bool requestResources(int customer_id, int request[]) { // 检查请求是否超过最大需求量 for (int i = 0; i < NUMBER_OF_RESOURCES; i++) { if (request[i] > max[customer_id][i] - allocation[customer_id][i]) { return false; } } // 检查请求是否超过可用资源数量 for (int i = 0; i < NUMBER_OF_RESOURCES; i++) { if (request[i] > available[i]) { return false; } } // 检查安全性并分配资源 if (isSafeState(customer_id, request)) { for (int i = 0; i < NUMBER_OF_RESOURCES; i++) { available[i] -= request[i]; allocation[customer_id][i] += request[i]; } return true; } else { return false; } } ``` 这样就可以通过调用`requestResources`函数来处理进程对资源的请求,并且使用`isSafeState`函数来判断当前状态是否安全。注意,上述代码只是一个简单的示例,实际应用中可能需要根据具体情况进行修改和完善。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值