銀行家算法
銀行家算法(Banker's Algorithm)是一個避免死鎖(Deadlock)的著名算法,是由艾茲格·迪傑斯特拉在1965年為T.H.E系統設計的一種避免死鎖產生的算法。它以銀行借貸系統的分配策略為基礎,判斷並保證系統的安全運行。
安全狀態
如果存在一個由系統中所有進程構成的安全序列P1,…,Pn,則系統處於安全狀態。安全狀態一定是沒有死鎖發生。
不安全狀態
不存在一個安全序列。不安全狀態不一定導致死鎖。
數據結構
1)可利用資源向量Available
是個含有m個元素的數組,其中的每一個元素代表一類可利用的資源數目。如果Available[j]=K,則表示系統中現有Rj類資源K個。
2)最大需求矩陣Max
這是一個n×m的矩陣,它定義了系統中n個進程中的每一個進程對m類資源的最大需求。如果Max[i,j]=K,則表示進程i需要Rj類資源的最大數目為K。
3)分配矩陣Allocation
這也是一個n×m的矩陣,它定義了系統中每一類資源當前已分配給每一進程的資源數。如果Allocation[i,j]=K,則表示進程i當前已分得Rj類資源的 數目為K。
4)需求矩陣Need。
這也是一個n×m的矩陣,用以表示每一個進程尚需的各類資源數。如果Need[i,j]=K,則表示進程i還需要Rj類資源K個,方能完成其任務。
Need[i,j]=Max[i,j]-Allocation[i,j]
算法原理
我們可以把操作系統看作是銀行家,操作系統管理的資源相當於銀行家管理的資金,進程向操作系統請求分配資源相當於用戶向銀行家貸款。
為保證資金的安全,銀行家規定:
(1) 當一個顧客對資金的最大需求量不超過銀行家現有的資金時就可接納該顧客;
(2) 顧客可以分期貸款,但貸款的總數不能超過最大需求量;
(3) 當銀行家現有的資金不能滿足顧客尚需的貸款數額時,對顧客的貸款可推遲支付,但總能使顧客在有限的時間里得到貸款;
(4) 當顧客得到所需的全部資金后,一定能在有限的時間里歸還所有的資金.
操作系統按照銀行家制定的規則為進程分配資源,當進程首次申請資源時,要測試該進程對資源的最大需求量,如果系統現存的資源可以滿足它的最大需求量則按當前的申請量分配資源,否則就推遲分配。當進程在執行中繼續申請資源時,先測試該進程本次申請的資源數是否超過了該資源所剩余的總量。若超過則拒絕分配資源,若能滿足則按當前的申請量分配資源,否則也要推遲分配。****
代碼
(樣例是按照課本西安電子科技大學第四版的)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e3 + 10;
int Avaialbe[N] = { 3, 3, 2 };//可利用資源向量
int Max[N][3] = { {7, 5, 3}, {3, 2, 2}, {9, 0, 2}, {2, 2, 2,}, {4, 3, 3} };//最大需求資源矩陣
int Allocation[N][3] = { {0, 1, 0}, {2, 0, 0}, {3, 0, 2}, {2, 1, 1}, {0, 0 , 2} };//已經分配的資源矩陣
int Need[N][3] = { {7, 4, 3}, {1, 2, 2}, {6, 0, 0}, {0, 1, 1}, {4, 3, 1} };//還需要的資源矩陣
int n, Request[3];
int path[5];//安全序列
int st[5];//分配標志位
void display(int i) {
cout << "P" << i << endl;
cout << "Avaialbe\tNeed\tAllocation\tAvaialbe+Allocation" << endl;
for (int j = 0; j < 3; j++)cout << Avaialbe[j] << ' ';
cout << "\t\t";
for (int j = 0; j < 3; j++)cout << Need[i][j] << ' ';
cout << "\t";
for (int j = 0; j < 3; j++)cout << Allocation[i][j] << ' ';
cout << "\t\t";
for (int j = 0; j < 3; j++)cout << Avaialbe[j] + Allocation[i][j] << ' ';
cout << endl;
}
bool isSafe(int u) {//安全性算法檢查 如果存在安全序列則返回true 安全序列在path數組里
if (u >= 5) {
return true;
}
bool flag = 0;
for (int i = 0; i < 5; i++) {//檢查是否處於安全狀態
if (!st[i]) {//當前進程還沒有滿足
if (Need[i][0] <= Avaialbe[0] && Need[i][1] <= Avaialbe[1] && Need[i][2] <= Avaialbe[2] && !st[i]) {//可以分配
display(i);//輸出當前進程狀態
for (int j = 0; j < 3; j++) {//分配給當前進程資源
Avaialbe[j] += Allocation[i][j];
Allocation[i][j] = 0;
}
flag = 1;
st[i] = 1;
path[u] = i;
break;
}
}
}
if (flag) {
isSafe(u + 1);
}
else return false;
}
bool Safe() {//銀行家算法
for (int i = 0; i < 3; i++) {//不能大於開始聲明的請求最大值
if (Request[i] > Max[n][i]) {
cout << "不能大於開始聲明的請求最大值" << endl;
return false;
}
}
for (int i = 0; i < 3; i++) {//不能大於當前系統剩余資源
if (Request[i] > Avaialbe[i]) {
cout << "不能大於當前系統剩余資源";
return false;
}
}
for (int i = 0; i < 3; i++) {//嘗試分配給該進程資源
Allocation[n][i] += Request[i];
Avaialbe[i] -= Request[i];
Need[n][i] -= Request[i];
}
if (isSafe(0))return true;//分配資源之后系統不能處於不安全狀態
return false;
}
int main() {
// freopen("a.txt", "r", stdin);
cout << "請輸入進程號(0~4):\n";
cin >> n;
cout << "請輸入該進程需要請求的三個資源:\n";
for (int i = 0; i < 3; i++)cin >> Request[i];
if (Safe()) {//執行安全檢查算法成功
cout << "\n存在一個安全序列:";
for (int i = 0; i < 5; i++) {
cout << path[i] << ' ';
}
cout << "\n所以該系統是安全的, 可以將資源分配給該進程!\n";
}
else {//執行安全性算法失敗
cout << "\n不存在一個安全序列, 不能將資源分配給改進程!\n";
}
}