死锁的产生、解除与预防

死锁是指两个或两个以上的进程在执行的过程中,因争夺资源而造成的一种互相等待的现象。

 

产生死锁的四个必要条件:

1、互斥条件:一个资源每次只能被一个进程使用。

2、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。(资源的部分分配)

3、不剥夺条件:进程已经获得的资源,在未使用完之前,不能强行剥夺。

4、循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

 

上述四个条件是产生死锁的四个必要条件,只要上述四个之中有一个不满足,就不会发生死锁。

 

根据上述条件,列出三条预防措施:

1、采用资源静态分配的策略,破坏“部分分配”条件。

2、允许进程剥夺使用其他进程占有的资源,从而破坏“不可剥夺”条件。

3、采用资源有序分配方法,破坏“环路”条件。

注意:互斥条件没法被破坏。

 

死锁避免算法里最著名的算法就是Dijkstra的银行家算法。

银行家算法:

        基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。

  设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断。

  (1)如果REQUEST [cusneed] [i]<= NEED[cusneed][i],则转(2);否则,出错。

  (2)如果REQUEST [cusneed] [i]<= AVAILABLE[cusneed][i],则转(3);否则,出错。

  (3)系统试探分配资源,修改相关数据:

  AVAILABLE[i]-=REQUEST[cusneed][i];

  ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];

  NEED[cusneed][i]-=REQUEST[cusneed][i];

  (4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。

安全性检查算法:

  (1)设置两个工作向量Work=AVAILABLE;    FINISH(全为false)

  (2)从进程集合中找到一个满足下述条件的进程,
  FINISH==false;
  NEED<=Work;
  如找到,执行(3);否则,执行(4)

  (3)设进程获得资源,可顺利执行,直至完成,从而释放资源。
  Work+=ALLOCATION;
  Finish=true;
  GOTO(2)

  (4)如所有的进程Finish= true,则表示安全;否则系统不安全。

 

银行家算法的代码实例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 5  //进程个数
#define M 3  //资源种类


int main()
{
	int i,j;
	int a;
	int Request[M];//请求资源距阵
	int Allocation[N][M];//已经分配资源矩阵
	int Need[N][M];//需求矩阵
	int Available[M];//可利用资源量

	//输入已经分配的资源
	printf("请输入已经分配的资源:\n");
	for(i=0;i<N;i++)
	{
		printf("请输入第 %d 个进程已经分配的资源:",i+1);
		for(j=0;j<M;j++)
			scanf("%d",&Allocation[i][j]);
	}

	//输入各个进程还需要的资源
	printf("\n请输入各个进程还需要的资源:\n");
	for(i=0;i<N;i++)
	{
		printf("请输入第 %d 个进程还需要的资源:",i+1);
		for(j=0;j<M;j++)
			scanf("%d",&Need[i][j]);
	}
	
	//输入可以利用的资源数据
	printf("\n请输入可以利用的资源数据:");
	for(i=0;i<M;i++)
		scanf("%d",&Available[i]);
	
	while(1)
	{
             start:printf("\n\n请输入是第几个进程发出资源请求:");
		scanf("%d",&a);//输入的是第几个进程的请求
		printf("\n第 %d 个进程资源请求数:",a);
		for(i=0;i<M;i++)
			scanf("%d",&Request[i]);
		
		//银行家算法第一步
		for(i=0;i<M;i++)
		{
			if(!(Request[i]<=Need[a-1][i]))
			{
				printf("P%d 非法请求!",a);
				printf("不可以分配给 P%d 进程!",a);
				goto start;
			}
		}

		//银行家算法第二步
		for(i=0;i<M;i++)
		{
			if(!(Request[i]<=Available[i]))
			{
				printf("P%d 进程阻塞!",a);
				printf("不可以分配给 P%d 进程!",a);
				goto start;
			}
		}

		//银行家算法第三步:试探性分配
		for(i=0;i<M;i++)
		{
			Available[i]=Available[i]-Request[i];
			Allocation[a-1][i]=Allocation[a-1][i]+Request[i];
			Need[a-1][i]=Need[a-1][i]-Request[i];
		}

		//银行家算法第四步:安全性检查
		int Finish[N]={0,0,0,0,0};
		int Work[M];
		for(i=0;i<M;i++)
			Work[i]=Available[i];

		int flag=1;

		while(flag==1)
		{
			for(i=0;i<N;i++)
			{
				for(j=0;j<M;j++)
				{
					if(Finish[i]==0 && Need[i][j]<=Work[j])
					{
						if(j==M-1)
						{
							Finish[i]=1;
							printf("\nP%d 进程安全性检查通过",i+1);
							for(j=0;j<M;j++)
								Work[j]=Work[j]+Allocation[i][j];
						}
					}
					continue;
				}
			}
			int sum=0;
			for(i=0;i<N;i++)
				sum=sum+Finish[i];
			if(sum==5)
				flag=0;

		}



		for(i=0;i<N;i++)
		{
			if(Finish[i]==0)
			{
				printf("试探性分配不成功!安全性检查不通过!");
				printf("\n不可以分配给 P%d 进程!",a);
				Available[i]=Available[i]+Request[i];
				Allocation[a-1][i]=Allocation[a-1][i]-Request[i];
				Need[a-1][i]=Need[a-1][i]+Request[i];
				goto start;
			}
		}


		printf("\n\n安全!可以分配给 P%d 进程!\n",a);

		//输出分配成功后资源占有、需求和可利用情况

		printf("\n资源占有情况:\n");
		for(i=0;i<N;i++)
		{
			printf("P%d 个进程已经分配的资源:",i+1);
			for(j=0;j<M;j++)
				printf(" %d ",Allocation[i][j]);
			printf("\n");
		}

		printf("\n资源需求情况:\n");
		for(i=0;i<N;i++)
		{
			printf("P%d 个进程还需要的资源:",i+1);
			for(j=0;j<M;j++)
				printf(" %d ",Need[i][j]);
			printf("\n");
		}

		printf("\n可以利用的资源数据:");
		for(i=0;i<M;i++)
			printf(" %d ",Available[i]);

		printf("\n");
	}
	return 0;
}


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值