死鎖避免——>銀行家算法

一、安全序列

所謂安全序列,就是指如果系統按照這種序列分配資源,則每個進程都能順利完成。只要能找到出一個安全序列,系統就是安全狀態。當然,安全序列可能有多個

如果分配了資源之後,系統中找不到任何一個安全序列,系統就進入不安全狀態。這就意味着之後可能所有進程都無法順利的執行下去。當然,如果有進程提前歸還了一些資源,那系統也有可能重新回到安全狀態,不過在分配資源之前總是要考慮到最壞的情況。

如果系統處於安全狀態,就一定不會發生死鎖。如果系統進入了不安全狀態,就可能發生死鎖(處於不安全狀態未必就是發生了了死鎖,但發生了死鎖時一定是在不安全狀態)

判斷是否處於安全序列?舉例1:安全序列

依次檢查剩餘可用資源(3,3,2)是否能滿足各進程的需求

可滿足p1需求,將p1加入安全序列,並更新可用資源值爲(5,3,2)

依次檢查剩餘可用資源(5,3,2)是否能滿足剩餘進程(不包括已加入安全序列的進程)的需求

可滿足p3需求,將p3加入安全序列,並更新可用資源值爲(7,4,3)

依次檢查剩餘可用資源(7,4,3)是否能滿足剩餘進程(不包括已加入安全序列的進程)的需求

……

此次類推,共五次循環檢查即可將5個進程都加入安全序列,最終可得一個安全序列。算法稱爲安全性算法。可以很方便地用代碼實現以上流程,每一輪檢查都從編號較小的進程開始檢查。

在實際做題時,手算會更快速,經對比發現,(3,3,2)可以滿足p1,p3,說明無論如何,這兩個進程的資源需求一定是可以滿足的,因此,p1,p3一定可以順序執行完,並歸還資源。可把p1,p3先加入安全序列。

(2,0,0)+(2,1,1)+(3,3,2)=(7,4,3)

剩下的p0,p2,p4都可被滿足,同理,這些進程都可以加入安全序列。

於是,5個進程全部加入安全序列,說明此時系統處於安全狀態,暫不可能發生死鎖

判斷是否處於安全序列?舉例2:不安全序列

經對比發現,(3,3,2)可以滿足p1,p3,說明無論如何,這兩個進程的資源需求一定是可以滿足的,因此,p1,p3一定可以順序執行完,並歸還資源。可把p1,p3先加入安全序列。

(2,0,0)+(2,1,1)+(3,3,2)=(7,4,3)

剩下的p0需要(8,4,2),p2需要(6,5,0),p4需要(4,3,4)

任何一個進程都不能被安全滿足

於是,無法找到任何一個安全序列,說明此時系統處於不安全狀態有可能發生死鎖

二、銀行家算法

用於避免死鎖

2.1 核心思想:

在進程提出資源申請時,先預判此次分配是否會導致系統進入不安全狀態。如果會進入不安全狀態,就暫時不答應這次請求,讓該進程先阻塞等待。

2.2 算法詳述

假設系統中有n個進程m種資源

每個進程在運行前先聲明對各種資源的最大需求數,則可用一個n*m的矩陣(可用二維數組實現)表示所有進程對各種資源的最大需求數,稱爲最大需求矩陣Max,Max[i,j]=k表示進程Pi最多需要K個資源Rj。

同理,系統可用用一個n*m的分配矩陣Allocation表示所有進程的資源分配情況。

Max-Allocation=Need矩陣,表示各進程最多還需要多少各類資源。

另外,用一個長度爲m的一維數組Avaliable表示當前系統中還有多少可用資源。

某進程Pi向系統申請資源,可用一個長度爲m的一維數組Request i 表示本次申請的各種資源量。

可用銀行家算法預判本次分配是否會導致進入不安全狀態:

(1)如果Request[ j ]<=Need[i,j](i<=j<=m)便轉向(2);否則認爲出錯。

(2)如果Request[ j ]<=Available[ j ](i<=j<=m)便轉向(3);否則表示尚無足夠資源,Pi必須等待。

(3)系統試探着把資源分配給進程Pi,並修改相應的數據(並非真的分配,修改數值只是爲了預判);

Available=Available-Request;

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

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

(4)操作系統執行安全性算法,檢查此次資源分配後,系統是否處於安全狀態。若安全,才正式分配;否則,回覆相應數據,讓進程阻塞等待。

三、總結

數據結構:

長度爲m的一維數組Available表示還有多少可用資源

n*m 矩陣Max 表示各進程對資源的最大需求數

n*m 矩陣Allocation表述已經給各進程分配了多少資源

Max-Allocation=Need 矩陣表示各進程此次申請的各種資源數

銀行家算法步驟:

(1)檢查此次申請是否超過了之前申明的最大需求數

(2)檢查此時系統剩餘的可用資源是否還能滿足這次請求

(3)試探着分配,更改數據結構

(4)用安全性算法檢查此次分配是否會導致系統進入不安全狀態

安全性算法步驟:

檢查當前的剩餘可用資源是否能滿足某個進程的嘴閥需求,如果可用,就把該進程加入安全序列,

並把該進程持有的資源全部回收。

不斷重複上述過程,看最終是否能讓所有進程都加入安全序列

 

系統處於不安全狀態未必死鎖,但死鎖時一定處於不安全狀態。

系統處於安全狀態一定不會死鎖。

五、代碼:

#include <iostream>
using namespace std;

#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();
bool Safe();
void Bank();
void showdata(int,int);

int main()
{
	Init();
	Safe();
	Bank();
}
void Init()                /*初始化算法*/
{
	int i,j;
	cout<<"請輸入進程的數目:";
	cin>>m;
	cout<<"請輸入資源的種類:";
	cin>>n;
	cout<<"請輸入每個進程最多所需的各資源數,按照"<<m<<"x"<<n<<"矩陣輸入"<<endl;
	for(i=0;i<m;i++)
		for(j=0;j<n;j++)
			cin>>MAX[i][j];
	cout<<"請輸入每個進程已分配的各資源數,也按照"<<m<<"x"<<n<<"矩陣輸入"<<endl;
	for(i=0;i<m;i++)
	{
		for(j=0;j<n;j++)
		{
			cin>>ALLOCATION[i][j];
			NEED[i][j]=MAX[i][j]-ALLOCATION[i][j];
			if(NEED[i][j]<0)
			{
				cout<<"您輸入的第"<<i+1<<"個進程所擁有的第"<<j+1<<"個資源數 錯誤,請重新輸入:"<<endl;
				j--;
				continue;
			}
		}
	}
	cout<<"請輸入各個資源現有的數目:"<<endl;
	for(i=0;i<n;i++)
	{
		cin>>AVAILABLE[i];
	}
}
void Bank()                /*銀行家算法*/
{
	int i,cusneed,flag = 0;
	char again;
	while(1)
	{
		showdata(n,m);////////////////////////////////////////////////////////////////////
		cout<<endl;
input:
		cout<<"請輸入要申請資源的進程號(注:第1個進程號爲0,依次類推)"<<endl;
		cin>>cusneed;
		if (cusneed > m)
		{
			cout<<"沒有該進程,請重新輸入"<<endl;
			goto input;
		}
		cout<<"請輸入進程所請求的各資源的數量"<<endl;
		for(i=0;i<n;i++)
		{
			cin>>REQUEST[cusneed][i];
		}
		for(i=0;i<n;i++)
		{
			if(REQUEST[cusneed][i]>NEED[cusneed][i])//如果用戶選擇的線程的第i個資源請求數>該線程該資源所需的數量
			{
				cout<<"您輸入的請求數超過進程的需求量!請重新輸入!"<<endl;
				goto input;
			}
			if(REQUEST[cusneed][i]>AVAILABLE[i])//如果用戶選擇的線程的第i個資源請求數>系統現有的第i個資源的數量
			{
				cout<<"您輸入的請求數超過系統有的資源數!請重新輸入!"<<endl;
				goto input;
			}
		}
		for(i=0;i<n;i++)//如果請求合理,那麼下面
		{
			AVAILABLE[i]-=REQUEST[cusneed][i];//系統可用資源減去申請了的
			ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];//線程被分配的資源加上已申請了的
			NEED[cusneed][i]-=REQUEST[cusneed][i];//線程還需要的資源減去已申請得到的
		}
		if(Safe())//AVAILABLE  ALLOCATION  NEED變動之後,是否會導致不安全
		{
			cout<<"同意分配請求!"<<endl;
		}
		else
		{
			cout<<"您的請求被拒絕!"<<endl;
			for(i=0;i<n;i++)
			{
				AVAILABLE[i]+=REQUEST[cusneed][i];
				ALLOCATION[cusneed][i]-=REQUEST[cusneed][i];
				NEED[cusneed][i]+=REQUEST[cusneed][i];
			}
		}
		for (i=0;i<n;i++)
		{
			if (NEED[cusneed][i] <= 0)
			{
				flag++;
			}
		}
		if (flag == n)//如果該進程各資源都已滿足條件,則釋放資源
		{
			for (i=0;i<n;i++)
			{
				AVAILABLE[i] += ALLOCATION[cusneed][i];
				ALLOCATION[cusneed][i] = 0;
				NEED[cusneed][i] = 0;
			}
			cout<<"線程"<<cusneed<<" 佔有的資源被釋放!"<<endl;
			flag = 0;
		}
		for(i=0;i<m;i++)//分配好了以後將進程的標識FINISH改成false
		{
			FINISH[i]=false;
		}
		cout<<"您還想再次請求分配嗎?是請按y/Y,否請按其它鍵"<<endl;
		cin>>again;
		if(again=='y'||again=='Y')
		{
			continue;
		}
		break;
	}
}

 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記錄每個進程是否安全 
	} 
	while (l<m)//正常的話,共執行m次 
	{ 
		int init_index = l; 
		for (i = 0; i< m; i++) 
		{ 
			if (FINISH[i] == true) 
			{ 
				continue; 
			} 
			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]; 
				} 
				p[l++] = i;//記錄進程號	
			} 
			else//如果超過繼續循環下一個進程 
			{			
				continue; 
			} 
			} 
			if (l==init_index) 
			{ 
				cout <<"系統是不安全的" << endl; 
				return false; 
			} 
		}//for循環 
		cout<< "系統是安全的"<<endl; 
		cout<< "安全序列:" <<endl; 
		for (i = 0; i< l; i++)//改了146行的i值,顯示資源分配給進程的順序 
		{ 
			cout << p[i]; 
			if (i != l - 1) 
			{ 
				cout<<"-->";
			} 
		} 
		cout<<""<<endl;		
		return true; 
	}
void showdata(int n,int m)   //顯示
{
	int i,j;
	cout<<endl;  
	cout<<"-------------------------------------------------------------"<<endl;  
	cout<<"系統可用的資源數爲:    ";
	for   (j=0;j<n;j++)       
		cout<<"    "<<AVAILABLE[j];      
	cout<<endl;   
	cout<<"各進程還需要的資源量:"<<endl; 
	for   (i=0;i<m;i++)   
	{
		cout<<"    進程"<<i<<":";   
 
		for   (j=0;j<n;j++)
			cout<<"     "<<NEED[i][j];   
		cout<<endl;   
	}   
 
	cout<<endl;   
	cout<<"各進程已經得到的資源量:    "<<endl<<endl;   
 
	for   (i=0;i<m;i++)   
	{
		cout<<"    進程"<<i<<":";   
 
		for   (j=0;j<n;j++)
			cout<<"     "<<ALLOCATION[i][j];
		cout<<endl;   
	}  
	cout<<endl; 
}   

參考博文:https://blog.csdn.net/wyf2017/article/details/80068608

https://blog.csdn.net/yaopeng_2005/article/details/6935235#commentsedit

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章