1. 程式人生 > >避免死鎖的銀行家演算法

避免死鎖的銀行家演算法

死鎖的定義>

   如果一組程序中的每一個程序都在等待僅由該組程序中的其他程序才能引發的事件,那仫該組程序就是死鎖的.

產生死鎖的必要條件>

    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)來對這個程式做一個介面出來,感覺好悲催哭,以後一定努力學習這方面的知識

  實現效果

   

  

    

    

   。。。