银行家算法详解
銀行家算法詳解
文章目錄
- 銀行家算法詳解
- 一、銀行家算法詳解
- 1.背景簡介
- 2.安全序列
- 3.實(shí)現(xiàn)方法:
- 4.檢查算法描述
- 5.案例
- 二、簡單實(shí)現(xiàn)
- 三、總結(jié)
一、銀行家算法詳解
- 銀行家算法是一種避免死鎖的方法
1.背景簡介
在銀行中,客戶申請貸款的數(shù)量是有限的,每個(gè)客戶在第一次申請貸款時(shí)要聲明完成該項(xiàng)目所需的最大資金量,在滿足所有貸款要求時(shí),客戶應(yīng)及時(shí)歸還。銀行家在客戶申請的貸款數(shù)量不超過自己擁有的最大值時(shí),都應(yīng)盡量滿足客戶的需要。在這樣的描述中,銀行家就好比操作系統(tǒng),資金就是資源,客戶就相當(dāng)于要申請資源的進(jìn)程。
銀行家算法是一種最有代表性的避免死鎖的算法。在避免死鎖方法中允許進(jìn)程動(dòng)態(tài)地申請資源,但系統(tǒng)在進(jìn)行資源分配之前,應(yīng)先計(jì)算此次分配資源的安全性,若分配不會(huì)導(dǎo)致系統(tǒng)進(jìn)入不安全狀態(tài),則分配,否則等待。
2.安全序列
- 安全序列是指某個(gè)進(jìn)程序列{P1,…,Pn}是安全的,即對于每一個(gè)進(jìn)程Pi(1≤i≤n),它以后尚需要的資源量不超過系統(tǒng)當(dāng)前剩余資源量與所有進(jìn)程Pj(j < i)當(dāng)前占有資源量之和。(即在分配過程中,不會(huì)出現(xiàn)某一進(jìn)程后續(xù)需要的資源量比其他所有進(jìn)程及當(dāng)前剩余資源量總和還大的情況)
注:存在安全序列則系統(tǒng)是安全的,如果不存在則系統(tǒng)不安全,但不安全狀態(tài)不一定引起死鎖。
3.實(shí)現(xiàn)方法:
為保證資金的安全,銀行家規(guī)定:
- (1) 當(dāng)一個(gè)顧客對資金的最大需求量不超過銀行家現(xiàn)有的資金時(shí)就可接納該顧客;
(即當(dāng)資源池中剩余的可利用資源 >=線程還需要的資源時(shí),就可以將可利用資源分配給此線程) - (2) 顧客可以分期貸款,但貸款的總數(shù)不能超過最大需求量;
(線程可以請求分配資源,但是請求的資源總數(shù)不能超過資源池中剩余的可利用資源) - (3) 當(dāng)銀行家現(xiàn)有的資金不能滿足顧客尚需的貸款數(shù)額時(shí),對顧客的貸款可推遲支付,但總能使顧客在有限的時(shí)間里得到貸款;
(當(dāng)線程池中的資源暫時(shí)不滿足當(dāng)前的線程所需時(shí),將此線程先暫時(shí)擱置,先將資源分配給能夠滿足的需求的其他線程,等到線程池中的資源足夠滿足先前擱置的線程時(shí),在將資源分配給擱置的線程) - (4) 當(dāng)顧客得到所需的全部資金后,一定能在有限的時(shí)間里歸還所有的資金。
(當(dāng)線程拿到所需要的所有資源,運(yùn)行結(jié)束后,將自身所有的資源放回資源池中)
當(dāng)一個(gè)進(jìn)程申請使用資源的時(shí)候,銀行家算法通過先 試探 分配給該進(jìn)程資源,然后通過安全性算法判斷給該進(jìn)程分配資源后的系統(tǒng)是否處于安全狀態(tài),若系統(tǒng)處于不安全狀態(tài),則試探分配作廢,讓該進(jìn)程繼續(xù)等待;
系統(tǒng)給當(dāng)前進(jìn)程分配資源時(shí),先檢查是否安全:
在滿足當(dāng)前的進(jìn)程X資源申請后,是否還能有足夠的資源去滿足下一個(gè)距最大資源需求最近的進(jìn)程(如某進(jìn)程最大需要5個(gè)單位資源,已擁有1個(gè),還尚需4個(gè)),若可以滿足,則繼續(xù)檢查下一個(gè)距最大資源需求最近的進(jìn)程,若均能滿足所有進(jìn)程,則表示為安全,可以允許給當(dāng)前進(jìn)程X分配其所需的資源申請,否則讓該進(jìn)程X進(jìn)入等待。
- 對于當(dāng)前進(jìn)程Pi X
- (1) 檢查if( Request[ i ][ j ]<=Need[ i ][ j ] ) goto (2)
else error(“進(jìn)程 i 對資源的申請量大于其說明的最大值 ”); - (2) 檢查 if ( Request[ i ][ j ]<=Available[ j ] ) goto (3)
else wait() ; /注意是等待!即在對后續(xù)進(jìn)程的需求資源判斷中,若出現(xiàn)不符合的則安全檢查結(jié)束,當(dāng)前進(jìn)程進(jìn)入等待/ - (3) 系統(tǒng)試探地把資源分給Pi 并修改各項(xiàng)屬性值 (具體是否成立,則根據(jù)安全檢查的結(jié)果)
- (4) 安全檢查,若檢查結(jié)果為安全,則(3)中執(zhí)行有效,否則分配作廢,使該P(yáng)i進(jìn)程進(jìn)入等待
4.檢查算法描述
- 向量Free[ j ]表示系統(tǒng)可分配給各進(jìn)程的Rj類資源數(shù)目,初始與當(dāng)前Available等值
- 向量Finish[ i ]表示進(jìn)程Pi在此次檢查中是否被滿足,初始均為false 當(dāng)有足有資源可分配給進(jìn)程時(shí),
- 1) 從進(jìn)程隊(duì)列中找一個(gè)能滿足下述條件的進(jìn)程Pi
- 2) 當(dāng)Pi獲得資源后,認(rèn)為Pi完成,釋放資源
(銀行家算法在避免死鎖角度上非常有效,但是需要在進(jìn)程運(yùn)行前就知道其所需資源的最大值,且進(jìn)程數(shù)也通常不是固定的,因此使用有限,但從思想上可以提供了解,可以轉(zhuǎn)換地應(yīng)用在其他地方)
假設(shè)資源P1申請資源,銀行家算法先試探的分配給它(當(dāng)然先要看看當(dāng)前資源池中的資源數(shù)量夠不夠),若申請的資源數(shù)量小于等于Available,然后接著判斷分配給P1后剩余的資源,能不能使進(jìn)程隊(duì)列的某個(gè)進(jìn)程執(zhí)行完畢,若沒有進(jìn)程可執(zhí)行完畢,則系統(tǒng)處于不安全狀態(tài)(即此時(shí)沒有一個(gè)進(jìn)程能夠完成并釋放資源,隨時(shí)間推移,系統(tǒng)終將處于死鎖狀態(tài))。
若有進(jìn)程可執(zhí)行完畢,則假設(shè)回收已分配給它的資源(剩余資源數(shù)量增加),把這個(gè)進(jìn)程標(biāo)記為可完成,并繼續(xù)判斷隊(duì)列中的其它進(jìn)程,若所有進(jìn)程都可執(zhí)行完畢,則系統(tǒng)處于安全狀態(tài),并根據(jù)可完成進(jìn)程的分配順序生成安全序列
如此就可避免系統(tǒng)存在潛在死鎖的風(fēng)險(xiǎn)。
5.案例
有5個(gè)進(jìn)程{P1,P2,P3,P4,P5} 。4類資源{R1,R2,R3,R4} 各自數(shù)量為6、3、4、2
T0時(shí)刻各進(jìn)程分配資源情況如下
T0時(shí)刻為安全狀態(tài),存在安全序列{P4,P1,P2,P3,P5} 如下:
二、簡單實(shí)現(xiàn)
#include <iostream> #include <cstdio> #include <cstring> using namespace std;const int maxpro = 100; //最大進(jìn)程數(shù) const int maxres = 100; //最大資源數(shù)int pro; //進(jìn)程數(shù) int res; //資源數(shù)int request[maxres];//進(jìn)程請求資源數(shù)目 //int R[maxres]; //總資源 int V[maxres]; //可提供 int C[maxpro][maxres]; //總需求 int A[maxpro][maxres]; //已分配 int vis[maxpro]; //表示第i個(gè)進(jìn)程是否已分配資源,1表示已分配 int path[maxpro]; //路徑//安全狀態(tài)判斷 bool safe() {int curV[maxres]; //目前可提供資源for(int i = 0; i < res; i++)curV[i] = V[i];memset(vis, 0, sizeof(vis));int flag = 1;for(int i1 = 0; i1 < pro; i1++) {int i;for(i = 0; i < pro; i++) {if(vis[i] == 1) continue;int flagpro = 1; //0表示未找到合適的進(jìn)程for(int j = 0; j < res; j++) {if(C[i][j] - A[i][j] > curV[j]) {flagpro = 0; break;}}if(flagpro) {path[i1] = i;vis[i] = 1;for(int k = 0; k < res; k++)curV[k] += A[i][k];break;}}if(i == pro) {flag = 0;}}return flag == 1; }void print() {cout << endl << "顯示當(dāng)前狀態(tài)" << endl;cout << "總需求矩陣C" << endl;for(int i = 0; i < pro; i++) {for(int j = 0; j < res; j++) {printf("%2d ", C[i][j]);}cout << endl;}cout << "已分配矩陣A" << endl;for(int i = 0; i < pro; i++) {for(int j = 0; j < res; j++) {printf("%2d ", A[i][j]);}cout << endl;}cout << "需求矩陣N (C-A)" << endl;for(int i = 0; i < pro; i++) {for(int j = 0; j < res; j++) {printf("%2d ", C[i][j] - A[i][j]);}cout << endl;}/* cout << "總資源向量R" << endl;for(int i = 0; i < res; i++)cout << R[i] << ' ';cout << endl;*/cout << "可提供資源向量V" << endl;for(int i = 0; i < res; i++)cout << V[i] << ' ';cout << endl << endl; }void bank() {while(true) {cout << endl << "請求資源輸入1,顯示當(dāng)前狀態(tài)輸入2, 結(jié)束輸入3" << endl;int k;cin >> k;if(k == 3) break;else if(k == 2) {print(); continue;}cout << "請輸入請求資源的進(jìn)程編號, 進(jìn)程號為0 - " << pro - 1 << endl;int proindex;cin >> proindex;cout << "請輸入此進(jìn)程每個(gè)資源需求數(shù)目" << endl;for(int i = 0; i < res; i++)cin >> request[i];//檢查該進(jìn)程所需要的資源是否已超過它所宣布的最大值int flag = 1; //flag為1表示沒超過,為0表示超過for(int i = 0; i < res; i++) {if(request[i] + A[proindex][i] > C[proindex][i])flag = 0;}if(flag == 0) {cout << "資源請求失敗,該進(jìn)程所需要的資源已超過總資源的最大值" << endl;continue;}//檢查系統(tǒng)當(dāng)前是否有足夠資源滿足該進(jìn)程的請求flag = 1; //flag為1有足夠資源,為0表示沒有for(int i = 0; i < res; i++) {if(request[i] > V[i])flag = 0;}if(flag == 0) {cout << "資源請求失敗,系統(tǒng)當(dāng)前沒有有足夠資源滿足該進(jìn)程的請求" << endl;continue;}//嘗試分配資源給該進(jìn)程,得到新的狀態(tài)for(int i = 0; i < res; i++) {A[proindex][i] += request[i]; //已分配資源矩陣A更新V[i] -= request[i]; //可提供資源向量V更新}//執(zhí)行安全性算法,若該新狀態(tài)是安全的,則分配完成;若新狀態(tài)是不安全的,則恢復(fù)原狀態(tài),阻塞該進(jìn)程if(safe()) {cout << "資源分配成功" << endl;cout << "安全路徑是:";for(int i = 0; i < pro; i++){cout << path[i] << " ";}cout << endl;for(int i = 0; i < pro; i++) {int j;for(j = 0; j < res; j++) {if(A[i][j] != C[i][j])break;}if(j == res){for(j = 0; j < res; j++) {V[j] += A[i][j];A[i][j] = 0;}}}}else {cout << "該狀態(tài)不安全,資源分配失敗" << endl;for(int i = 0; i < res; i++) {A[proindex][i] -= request[i]; //已分配資源矩陣A更新V[i] += request[i]; //可提供資源向量V更新}}} }int main() {cout << "請輸入總資源數(shù): " << endl;cin >> res;cout << "請輸入總進(jìn)程數(shù): " << endl;cin >> pro; /*cout << "請分別輸入每個(gè)資源的數(shù)目(R向量),目前有" << res << "個(gè)資源" << endl;for(int i = 0; i < res; i++)cin >> R[i];*/cout << "請分別輸入每個(gè)資源的已分配數(shù)目(V向量),目前有" << res << "個(gè)資源" << endl;for(int i = 0; i< res; i++)cin >> V[i];cout << "請輸入總需求矩陣C,共有" << res << "個(gè)資源," << pro << "個(gè)進(jìn)程" << endl;cout << "格式: 每行輸入單個(gè)進(jìn)程的總需求資源數(shù)目, 輸入" << pro << "行" << endl;for(int i = 0; i < pro; i++)for(int j = 0 ; j < res; j++)cin >> C[i][j];cout << "請輸入已分配矩陣A,共有" << res << "個(gè)資源," << pro << "個(gè)進(jìn)程" << endl;cout << "格式: 每行輸入單個(gè)進(jìn)程的已分配資源數(shù)目, 輸入" << pro << "行" << endl;for(int i = 0; i < pro; i++)for(int j = 0 ; j < res; j++)cin >> A[i][j];bank();return 0; }三、總結(jié)
- 死鎖避免的基本思想是動(dòng)態(tài)地檢測資源分配狀態(tài),以確保循環(huán)等待條件不成立,從而確保系統(tǒng)處于安全狀態(tài)。所謂安全狀態(tài)是指:如果系統(tǒng)能按某個(gè)順序?yàn)槊總€(gè)進(jìn)程分配資源(不超過其最大值),那么系統(tǒng)狀態(tài)是安全的,換句話說就是,如果存在一個(gè)安全序列,那么系統(tǒng)處于安全狀態(tài)。
- 資源分配圖算法和銀行家算法是兩種經(jīng)典的死鎖避免的算法,其可以確保系統(tǒng)始終處于安全狀態(tài)。
- 其中,資源分配圖算法應(yīng)用場景為每種資源類型只有一個(gè)實(shí)例(申請邊,分配邊,需求邊,不形成環(huán)才允許分配),而銀行家算法應(yīng)用于每種資源類型可以有多個(gè)實(shí)例的場景。
總結(jié)
- 上一篇: 分段翻转链表
- 下一篇: 力扣--统计全1子矩阵