如何避免死锁?

在资源分配的过程中,防止系统进入不安全的状态中,避免死锁的发生
安全状态:系统能按照某种进程推进顺序为每个进程分配其所需的资源,直到满足每个进程对资源的最大需求,使得每个进程都能获得其所需的资源
在了解了什么是安全状态之后,就大概知道了避免死锁的基本思想,就是确保系统始终处于安全状态。当一个系统开始时处于安全状态时,有一个进程请求一个可用资源时,系统需对该进程的请求进行计算,若将资源分配给进程后系统仍处于安全状态,才将资源分配给进程。

银行家算法

银行家算法是最避免死锁的具有代表性的算法

  • 每一个新的进程进入系统之前,必须申明在运行中,其需要每种资源类型的最大数目,其数目不能超过系统所拥有的资源总量。当进程请求一组资源时,系统必须首先确定是否有足够的资源分配给该进程。如果有,则继续计算分配完毕后系统是否处于安全状态,若仍处于安全状态则分配资源,否则不分配

代码讲解

  • 安全检测算法 (1)设置两个向量:①工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work= Available;②Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]=false;当有足够资源分配给进程时,再令Finishi]= true. (2)从进程集合中找到一个能满足下述条件的进程: ①Finish[i]= false; ②Need[i, j]≤Work[j]; 若找到,执行步骤(3),否则,执行步骤(4)。 (3)当进程P; 获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[j] = Work[j] + Allocation[i, j];
 Finish[i]= true;)
 go to step 2;

(4)如果所有进程的Finish[i] =true都满足,则表示系统处于安全状态;否则,系统处于不安全状态。

  • 资源分配请求模块 设res是进程P的请求向量,如果res[j]=K,表示进程P需要K个t类型的资源。当P发出资源请求后,系统按下述步骤进行检查: (1)如果res[j]≤Need[i, j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。 (2)如果res[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,P:须等待。 (3)系统试探着把资源分配给进程P,,并修改下面数据结构中的数值:
Available[j] = Available[j] - res[j];
 Allocation[i, j] = Allocation[i, j] + res[j];
 Need[i, j] = Need[i, j]- res[i];

(4)系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程P,以完成本次分配:否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程P等待。

程序流程图

银行家算法代码Python4类资源 银行家算法代码讲解_资源分配

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include<stdbool.h>
#include<iostream>
using namespace std;




//系统中所有进程数量
//const int PROCESSES_NUMBER = 5;

#define PROCESSES_NUMBER	5


typedef struct {
	int	A;
	int	B;
	int	C;
}RESOURCE;

//最大需求矩阵
RESOURCE Max[PROCESSES_NUMBER];

//已分配资源数矩阵
RESOURCE Allocation[PROCESSES_NUMBER];

//需求矩阵
RESOURCE Need[PROCESSES_NUMBER];

//可用资源向量
RESOURCE Available = { 3,3,2 };
//安全序列
int safe[PROCESSES_NUMBER];
//可提供资源
RESOURCE Work;


//试探分配
void ProbeAlloc(int process, RESOURCE *res)
{
	Available.A -= res->A;
	Available.B -= res->B;
	Available.C -= res->C;

	Allocation[process].A += res->A;
	Allocation[process].B += res->B;
	Allocation[process].C += res->C;

	Need[process].A -= res->A;
	Need[process].B -= res->B;
	Need[process].C -= res->C;
}

//若试探分配后进入不安全状态,将分配回滚
void RollBack(int process, RESOURCE *res)
{
	Available.A += res->A;
	Available.B += res->B;
	Available.C += res->C;

	Allocation[process].A -= res->A;
	Allocation[process].B -= res->B;
	Allocation[process].C -= res->C;

	Need[process].A += res->A;
	Need[process].B += res->B;
	Need[process].C += res->C;
}

//安全性检查
bool SafeCheck()
{
	//RESOURCE	Work = Available;
	Work = Available;
	bool		Finish[PROCESSES_NUMBER] = { false,false,false,false,false };
	int		i;
	int		j = 0;

	for (i = 0; i < PROCESSES_NUMBER; i++)
	{
		//是否已检查过
		if (Finish[i] == false)
		{
			//是否有足够的资源分配给该进程
			if (Need[i].A <= Work.A && Need[i].B <= Work.B && Need[i].C <= Work.C)
			{
				//有则使其执行完成,并将已分配给该进程的资源全部回收
				Work.A += Allocation[i].A;
				Work.B += Allocation[i].B;
				Work.C += Allocation[i].C;
				Finish[i] = true;
				safe[j++] = i;
				i = -1;				//重新进行遍历
			}
		}
	}

	//如果所有进程的Finish向量都为true则处于安全状态,否则为不安全状态
	for (i = 0; i < PROCESSES_NUMBER; i++)
	{
		if (Finish[i] == false)
		{
			return false;
		}
	}
	return true;
}

//资源分配请求
bool request(int process, RESOURCE *res)
{
	//request向量需小于Need矩阵中对应的向量
	if (res->A <= Need[process].A && res->B <= Need[process].B && res->C <= Need[process].C)
	{
		//request向量需小于Available向量
		if (res->A <= Available.A && res->B <= Available.B && res->C <= Available.C)
		{
			//试探分配
			ProbeAlloc(process, res);

			//如果安全检查成立,则请求成功,否则将分配回滚并返回失败
			if (SafeCheck())
			{
				return true;
			}
			else
			{
				printf("安全性检查失败。原因:系统将进入不安全状态,有可能引起死锁。\n");
				printf("正在回滚...\n");
				RollBack(process, res);
			}
		}
		else
		{
			printf("安全性检查失败。原因:请求向量大于可利用资源向量。\n");
		}
	}
	else
	{
		printf("安全性检查失败。原因:请求向量大于需求向量。\n");
	}
	return false;
}

//输出资源分配表
void PrintTable()
{
	printf("\t\t\t*********资源分配表*********\n");
	
	printf("Process       Max          Allocation          Need          Available\n");
	printf("          A    B    C     A    B    C       A    B    C      A    B    C\n");
	printf("  P0      %d    %d    %d     %d    %d    %d       %d    %d    %d      %d    %d    %d\n", Max[0].A, Max[0].B, Max[0].C, Allocation[0].A, Allocation[0].B, Allocation[0].C, Need[0].A, Need[0].B, Need[0].C, Available.A, Available.B, Available.C);
	
	
	printf("  P1      %d    %d    %d     %d    %d    %d       %d    %d    %d\n", Max[1].A, Max[1].B, Max[1].C, Allocation[1].A, Allocation[1].B, Allocation[1].C, Need[1].A, Need[1].B, Need[1].C);
	printf("  P2      %d    %d    %d     %d    %d    %d       %d    %d    %d\n", Max[2].A, Max[2].B, Max[2].C, Allocation[2].A, Allocation[2].B, Allocation[2].C, Need[2].A, Need[2].B, Need[2].C);
	printf("  P3      %d    %d    %d     %d    %d    %d       %d    %d    %d\n", Max[3].A, Max[3].B, Max[3].C, Allocation[3].A, Allocation[3].B, Allocation[3].C, Need[3].A, Need[3].B, Need[3].C);
	printf("  P4      %d    %d    %d     %d    %d    %d       %d    %d    %d\n", Max[4].A, Max[4].B, Max[4].C, Allocation[4].A, Allocation[4].B, Allocation[4].C, Need[4].A, Need[4].B, Need[4].C);
	printf("\n");
}

int main()
{
	char ch = 'y';
	cout << "请输入最大需求矩阵" << endl;
	for (int i = 0; i < PROCESSES_NUMBER; i++) {
		cin >> Max[i].A >> Max[i].B >> Max[i].C;
	}
	cout << "请输入已分配资源矩阵" << endl;
	for (int i = 0; i < PROCESSES_NUMBER; i++) {
		cin >> Allocation[i].A >> Allocation[i].B >> Allocation[i].C;
	}
	cout << "请输入需求矩阵" << endl;
	for (int i = 0; i < PROCESSES_NUMBER; i++) {
		cin >> Need[i].A >> Need[i].B >> Need[i].C;
	}


	printf("先检查初始状态是否安全。\n");
	if (SafeCheck())
	{
		printf("系统处于安全状态。\n");
		printf("安全序列是{P%d,P%d,P%d,P%d,P%d}。\n", safe[0], safe[1], safe[2], safe[3], safe[4]);
	}
	else
	{
		printf("系统处于不安全状态。程序将退出...\n");
		return 0;
	}
	while(ch == 'y' || ch == 'Y')
	{
		int		process;
		RESOURCE	res;//请求向量
		PrintTable();
		printf("请依次输入请求分配的进程和对三类资源的请求数量:");
		scanf("%d%d%d%d", &process, &res.A, &res.B, &res.C);
		if (request(process, &res))
		{
			printf("分配成功。\n");
			printf("安全序列是{P%d,P%d,P%d,P%d,P%d}。\n", safe[0], safe[1], safe[2], safe[3], safe[4]);
			if (Need[process].A == 0 && Need[process].B == 0 && Need[process].C == 0)
			{
				Available.A += Max[process].A;
				Available.B += Max[process].B;
				Available.C += Max[process].C;
			}
			int count = 0;
			for (int i = 0; i < 5; i++)
			{
				if (Need[i].A == 0 && Need[i].B == 0 && Need[i].C == 0)
						count++;				
			}
			if (count == 5)
			{
				cout << "进程已全部分配完毕" << endl;
				return 0;
			}
		}
		else
		{
			printf("分配失败。\n");
		}
		printf("是否继续分配?(Y/N):\n");
		cin >> ch;
		cout << endl;
	} 

	return 0;
}