銀行家演算法是Dijkstra在1965年提出的一種避免死鎖的演算法。銀行家演算法陳述如下:
1)   當一個程式提出一個資源的請求時,假定分配給它,並呼叫檢查系統狀態安全性的演算法。如果系統是安全的,則對申請者的假分配變為實際的分配。否則,推遲它的請求,讓其阻塞等待。
2)   檢查系統狀態安全性的演算法。根據系統剩餘的資源情況,銀行家進行檢查,看滿足請求者的要求後,是否仍是系統中的所有程式都能正常完成(即能找到一個程式完成序列)。若能,系統是安全的。否則,系統是不安全的。
銀行家演算法主要如下:
輸入:資源個數m、程式個數n、最大請求矩陣max、分配矩陣allocation
輸出:程式執行情況和安全狀況提示(如果安全,輸出一個可能的程式完成序列)
主要演算法:
1)   初始化,輸入各個引數,初始化各變數
 
2)   判斷系統安全性
程式中安全性演算法的描述如下:
a.   設定如下兩個工作向量:
Work:表示系統可提供給程式繼續執行的各類資源的空閒資源數目,它含有m個元素,執行安全性演算法開始時,Work=Available。
Finish:表示系統是否有足夠的資源分配給程式,使之執行完成。開始時,Finish[i]=false;當有足夠的資源分配給程式Pi時,令Finish[i]=true。
b.   從程式集合中找到一個能滿足下列條件的程式:
Finish[i]= false;
Need[i] <= Work;
如果找到了就執行步驟c,否則執行步驟d。
c.   當程式Pi獲得資源後,可執行直到完成,並釋放出分配給它的資源,故應執行
Work = Allocation[i]+Work;
Finish[i]=true;
然後轉向b。
d.   若所有程式中的Finish[i]都是true,則表示系統處於安全狀態;否則,系統處於不安全狀態。
 
3)   當系統請求資源時,呼叫系統狀態安全性演算法
系統狀態安全性演算法:
當某一程式提出資源申請時,系統須做出判斷,能否將所申請資源分配給該程式。設Request[i]是程式Pi的請求向量,Request[i][j]=k表示程式Pi請求分配 j類資源有k個。當Pi發出資源請求後,系統按照下述步驟進行檢查:
a. 如果Request[i]<= Need[i],則轉向b;否則出錯,因為程式所需要的資源數已超過它所宣佈的最大值;
b.  如果Request[i]<=Available,則轉向步驟c;否則,表示系統中尚無足夠的資源滿足程式Pi的申請,讓程式Pi等待。
c. 假設系統把申請的資源分配給程式Pi,則對應下面的資料結構進行修改:
Available= Available-Request[i];
           Allocation[i]= Allocation[i]+Request[i];
Need[i]= Need[i]-Request[i];
d. 系統執行安全性演算法,檢查此次資源分配後,系統是否處於安全狀態。若安全,就將資源分配給Pi,滿足其資源申請要求;否則,讓程式等待,並恢復原來的資源分配狀態。
 
資料結構:
class bank
{
private:
    int m;                //資源數量
    int n;                //程式數量
    int available[M];     //可利用資源向量
    int max[M][N];        //最大需求矩陣
    int allocation[M][N]; //分配矩陣
    int need[M][N];       //需求矩陣
public:
    bool Initilize();     //初始化各變數
    bool IsSafe();        //檢查系統是否安全
    bool Resoure_allocate();//分配資源
    bool IsFinish();      //檢查系統是否執行完畢
};
 
 
測試用例:
本測試用例為《作業系統原理教程(第二版)》P62頁用例,先給P2分配一個印表機,分配成功,然後分配給P5一臺印表機,分配失敗,然後按照P4,P1,P5,P2,P3執行系統。
 
Available=(1,0,2,0)
程式
磁帶機
繪圖機
印表機
光碟機
P1
3
0
1
1
P2
0
1
0
0
P3
1
1
1
0
P4
1
1
0
1
P5
0
0
0
0
程式當前的分配矩陣Allocation
程式
磁帶機
繪圖機
印表機
光碟機
P1
1
1
0
0
P2
0
1
1
2
P3
3
1
0
0
P4
0
0
1
0
P5
2
1
1
0
程式當前的剩餘請求矩陣Need
程式
磁帶機
繪圖機
印表機
光碟機
P1
4
1
1
1
P2
0
2
1
2
P3
4
2
1
0
P4
1
1
1
1
P5
2
1
1
0
各個程式的最大請求矩陣Max
測試資料:(直接複製到終端中即可)
4
5
4 1 1 1
0 2 1 2
4 2 1 0
1 1 1 1
2 1 1 0
3 0 1 1
0 1 0 0
1 1 1 0
1 1 0 1
0 0 0 0
1 0 2 0
1
2
1
4
2
1
3
2
1
0
0
1
0
1
1
4
0
2
4
1
1
4
2
1
1
1
1
1
3
2
2
0
3
2
1
1
執行結果:
輸入資源數量:4
輸入程式數量:5
輸入最大請求矩陣 5X4
4 1 1 1
0 2 1 2
4 2 1 0
1 1 1 1
2 1 1 0
輸入分配矩陣 5X4
3 0 1 1
0 1 0 0
1 1 1 0
1 1 0 1
0 0 0 0
輸入可利用資源向量 1X4
1 0 2 0
安全序列是
3 0 1 2 4
輸入執行程式號:1
請求資源號:2
請求數量:1
安全序列是
3 0 1 2 4
輸入執行程式號:4
請求資源號:2
請求數量:1
沒有安全序列
系統不安全,等待
輸入執行程式號:3
請求資源號:2
請求數量:1
安全序列是
0 1 2 4
程式3執行完畢
輸入執行程式號:0
請求資源號:0
請求數量:1
安全序列是
0 1 2 4
輸入執行程式號:0
請求資源號:1
請求數量:1
安全序列是
1 2 4
程式0執行完畢
輸入執行程式號:4
請求資源號:0
請求數量:2
安全序列是
1 2 4
輸入執行程式號:4
請求資源號:1
請求數量:1
安全序列是
4 1 2
輸入執行程式號:4
請求資源號:2
請求數量:1
安全序列是
1 2
程式4執行完畢
輸入執行程式號:1
請求資源號:1
請求數量:1
安全序列是
1 2
輸入執行程式號:1
請求資源號:3
請求數量:2
安全序列是
2
程式1執行完畢
輸入執行程式號:2
請求資源號:0
請求數量:3
安全序列是
2
輸入執行程式號:2
請求資源號:1
請求數量:1
安全序列是
 
程式2執行完畢
所有程式執行完畢
  1. #include <iostream>  
  2. #include <cstdlib>  
  3. #define M 16  
  4. #define N 16  
  5. using namespace std;  
  6.  
  7. class bank  
  8. {  
  9. private:  
  10.     int m;                //資源數量  
  11.     int n;                //程式數量  
  12.     int available[M];     //可利用資源向量  
  13.     int max[M][N];        //最大需求矩陣  
  14.     int allocation[M][N]; //分配矩陣  
  15.     int need[M][N];       //需求矩陣  
  16. public:  
  17.     bool Initilize();     //初始化各變數  
  18.     bool IsSafe();        //檢查系統是否安全  
  19.     bool Resoure_allocate();//分配資源  
  20.     bool IsFinish();      //檢查系統是否執行完畢  
  21. };  
  22.  
  23. int main()  
  24. {  
  25.     bank process;  
  26.  
  27.     if (!process.Initilize())   //初始化  
  28.     {  
  29.         cout<<"輸入錯誤"<<endl;  
  30.     }  
  31.  
  32.     if (!process.IsSafe())      //檢查系統執行初是否安全  
  33.     {  
  34.         return 0;  
  35.     }  
  36.  
  37.     while (true)  
  38.     {  
  39.         process.Resoure_allocate();     //根據各程式需要分配資源  
  40.         if (process.IsFinish())         //檢查系統是否執行完畢  
  41.         {  
  42.             cout<<"所有程式執行完畢"<<endl;  
  43.             break;  
  44.         }  
  45.     }  
  46.     system("PAUSE");  
  47.     return 0;  
  48. }  
  49.  
  50. bool bank::Initilize()  
  51. {  
  52.     int i,j;  
  53.     cout<<"輸入資源數量:";  
  54.     cin>>m;  
  55.     cout<<"輸入程式數量:";  
  56.     cin>>n;  
  57.     cout<<"輸入最大請求矩陣 "<<n<<"X"<<m<<endl;  
  58.     for (i = 0; i < n; i++)  
  59.     {  
  60.         for (j = 0; j < m; j++)  
  61.         {  
  62.             cin>>max[i][j];  
  63.         }  
  64.     }  
  65.     cout<<"輸入分配矩陣 "<<n<<"X"<<m<<endl;  
  66.     for (i = 0; i < n; i++)  
  67.     {  
  68.         for (j = 0; j < m; j++)  
  69.         {  
  70.             cin>>allocation[i][j];  
  71.         }  
  72.     }  
  73.     for (i = 0; i < n; i++)  
  74.     {  
  75.         for (j = 0; j < m; j++)  
  76.         {  
  77.             need[i][j]=max[i][j]-allocation[i][j];  
  78.             if (need[i][j] < 0)  
  79.             {  
  80.                 return false;  
  81.             }  
  82.         }  
  83.     }  
  84.     cout<<"輸入可利用資源向量 "<<1<<"X"<<m<<endl;  
  85.     for (i = 0; i < m; i++)  
  86.     {  
  87.         cin>>available[i];  
  88.         if (available[i] < 0)  
  89.         {  
  90.             return false;  
  91.         }  
  92.     }  
  93.     return true;  
  94. }  
  95.  
  96. bool bank::IsSafe()  
  97. {  
  98.     int i,j,k,result[N],work[M],finish[N];  
  99.     for (i = 0; i < m; i++)  
  100.     {  
  101.         work[i]=available[i];  
  102.     }  
  103.     for (i = 0; i < n; i++)                 //標識變數初始化  
  104.     {  
  105.         finish[i]=false;  
  106.     }  
  107.     for (i = 0, k = 0; i < n; i++)  
  108.     {  
  109.         if (!finish[i])  
  110.         {  
  111.             for (j = 0; j < m; j++)  
  112.             {  
  113.                 if (need[i][j] > work[j])      //目前無法滿足該程式  
  114.                 {  
  115.                     break;  
  116.                 }  
  117.             }  
  118.  
  119.             if (j == m)                     //可以滿足該程式  
  120.             {  
  121.                 result[k++]=i;  
  122.                 for (j = 0; j < m; j++) //將現有可用資源數加上第i程式已經分配了的  
  123.                 {  
  124.                     work[j]+=allocation[i][j];  
  125.                 }  
  126.                 finish[i]=true;  
  127.                 i=-1;                       //從頭掃描  
  128.             }  
  129.         }  
  130.     }  
  131.     for (i = 0; i < n; i++)  
  132.     {  
  133.         if (!finish[i])  
  134.         {  
  135.             cout<<"沒有安全序列"<<endl;  
  136.             return false;  
  137.         }  
  138.     }  
  139.     cout<<"安全序列是"<<endl;  
  140.     for (i = 0; i < n; i++)  
  141.     {  
  142.         for ( j = 0; j < m; j++)            //如果程式已經執行完畢,則安全序列中不再輸出  
  143.         {  
  144.             if (need[result[i]][j] != 0)  
  145.             {  
  146.                 break;  
  147.             }  
  148.         }  
  149.         if (j == m)  
  150.         {  
  151.             continue;  
  152.         }  
  153.         cout<<result[i]<<" ";  
  154.     }  
  155.     cout<<endl;  
  156.     return true;  
  157. }  
  158.  
  159. bool bank::Resoure_allocate()  
  160. {  
  161.     int i,process_id,source_id,amount;  
  162.     cout<<"輸入執行程式號:";  
  163.     cin>>process_id;  
  164.     cout<<"請求資源號:";  
  165.     cin>>source_id;  
  166.     cout<<"請求數量:";  
  167.     cin>>amount;  
  168.  
  169.     if (amount > need[process_id][source_id])  
  170.     {  
  171.         cout<<"請求不合法,終止執行"<<endl;  
  172.         return false;  
  173.     }  
  174.  
  175.     if (amount > available[source_id])  
  176.     {  
  177.         cout<<"請求無法滿足,等待"<<endl;  
  178.         return false;  
  179.     }  
  180.  
  181.     available[source_id]-=amount;                   //假定分配資源  
  182.     allocation[process_id][source_id]+=amount;  
  183.     need[process_id][source_id]-=amount;  
  184.  
  185.     if (!IsSafe())                                  //檢查系統是否安全  
  186.     {  
  187.         available[source_id]+=amount;  
  188.         allocation[process_id][source_id]-=amount;  
  189.         need[process_id][source_id]+=amount;  
  190.         cout<<"系統不安全,等待"<<endl;  
  191.         return false;  
  192.     }  
  193.  
  194.     for ( i = 0; i < m; i++)                        //檢視程式是否執行完畢  
  195.     {  
  196.         if (allocation[process_id][i] != max[process_id][i])  
  197.         {  
  198.             break;  
  199.         }  
  200.     }  
  201.  
  202.     if (i == m)                                     //程式執行完畢  
  203.     {  
  204.         for ( i = 0; i < m; i++)  
  205.         {  
  206.             available[i]+=allocation[process_id][i];  
  207.             allocation[process_id][i]=0;  
  208.             need[process_id][i]=0;  
  209.         }  
  210.         cout<<"程式"<<process_id<<"執行完畢"<<endl;  
  211.     }  
  212.     return true;  
  213. }  
  214.  
  215. bool bank::IsFinish()  
  216. {  
  217.     int i,j,finish[N];  
  218.  
  219.     for ( i = 0; i < n; i++)  
  220.     {  
  221.         finish[i]=false;  
  222.     }  
  223.  
  224.     for ( i = 0; i < n; i++)  
  225.     {  
  226.         for ( j = 0; j < m; j++)  
  227.         {  
  228.             if (need[i][j] != 0)  
  229.             {  
  230.                 break;  
  231.             }  
  232.         }  
  233.         if (j == m)  
  234.         {  
  235.             finish[i]=true;  
  236.         }  
  237.     }  
  238.  
  239.     for ( i = 0; i < n; i++)  
  240.     {  
  241.         if (finish[i] == false)  
  242.         {  
  243.             break;  
  244.         }  
  245.     }  
  246.     if (i != n)  
  247.     {  
  248.         return false;  
  249.     }  
  250.     return true;  
  251. }