銀行家算法學習筆記


https://www.cnblogs.com/chuxiuhong/p/6103928.html


死鎖避免——銀行家算法的應用背景

  1、要想說銀行家,首先得說死鎖問題,因為銀行家算法就是為了死鎖避免提出的。那么,什么是死鎖?簡單的舉個例子:倆人吃餃子,一個人手里拿着醬油,一個人手里拿着醋,拿醬油的對拿着醋的人說:“你把醋給我,我就把醬油給你”;拿醋的對拿着醬油的人說:“不,你把醬油給我,我把醋給你。”

  於是,倆人這兩份調料是永遠吃不上了。這就是死鎖。

  2、那么,為啥這個算法叫銀行家算法?因為這個算法同樣可以用於銀行的貸款業務。讓我們考慮下面的情況。

  • 一個銀行家共有20億財產
  • 第一個開發商:已貸款15億,資金緊張還需3億。
  • 第二個開發商:已貸款5億,運轉良好能收回。
  • 第三個開發商:欲貸款18億

  在這種情況下,如果你是銀行家,你怎么處理這種情況?一個常規的想法就是先等着第二個開發商把錢收回來,然后手里有了5個億,再把3個億貸款給第一個開發商,等第一個開發商收回來18個億,然后再把錢貸款給第三個開發商。或者呢,先借給第一個開發商3億,等他還了錢給第三個開發商,此時第二個開發商沒啥需求。
  這里面什么值得學習呢?最重要的就是眼光放長一點,不要只看着手里有多少錢,同時要注意到別人欠自己的錢怎么能收回來

  那么正經點說這個問題,第一個例子中:醋和醬油是資源,這倆吃餃子的是進程;第二個例子中:銀行家是資源,開發商是進程。在操作系統中,有內存,硬盤等等資源被眾多進程渴求着,那么這些資源怎么分配給他們才能避免“銀行家破產”的風險?


銀行家算法

安全序列:安全序列是指對當前申請資源的進程排出一個序列,保證按照這個序列分配資源完成進程,不會發生“醬油和醋”的尷尬問題。所以我們需要對請求進程排出個分配的序列!

我們假設有進程P1,P2,.....Pn。則安全序列要求滿足:Pi(1<=i<=n)需要資源<=剩余資源 + 分配給Pj(1 <= j < i)資源。為什么等號右邊還有已經被分配出去的資源?想想銀行家那個問題,分配出去的資源就好比第二個開發商,人家能還回來錢,咱得把這個考慮在內。

我們定義下面的數據結構(想想那個銀行家的例子)

int n,m; //系統中進程總數n和資源種類總數m int Available[1..m]; //資源當前可用總量 int Allocation[1..n,1..m]; //當前給分配給每個進程的各種資源數量 int Need[1..n,1..m];//當前每個進程還需分配的各種資源數量 int Work[1..m]; //當前可分配的資源 bool Finish[1..n]; //進程是否結束

安全判定算法

1.初始化

Work = Available(動態記錄當前剩余資源) Finish[i] = false(設定所有進程均未完成)

2.查找可執行進程Pi(未完成但目前剩余資源可滿足其需要,這樣的進程是能夠完成的)

Finish[i] = false Need[i] <= Work 如果沒有這樣的進程Pi,則跳轉到第4步

3.(若有則)Pi一定能完成,並歸還其占用的資源,即:

Finish[i] = true Work = Work +Allocation[i] GOTO 第2步,繼續查找

4.如果所有進程Pi都是能完成的,即Finish[i]=ture
則系統處於安全狀態,否則系統處於不安全狀態

偽代碼:

Boolean Found; Work = Available; Finish[1..n] = false; while(true){ //不斷的找可執行進程 Found = false; for(i=1; i<=n; i++){ if(Finish[i]==false && Need[i]<=Work){ Work = Work + Allocation[i];//把放出去的貸款也當做自己的資產 Finish[i] = true; Found = true; } } if(Found==false)break; } for(i=1;i<=n;i++) if(Finish[i]==false)return “deadlock”; //如果有進程是完不成的,那么就是有死鎖

示例

舉個實際例子,假設下面的初始狀態:

process Allocation Need Available
  A B C A B C A B C
P0 0 1 0 7 4 3 3 3 2
P1 2 0 0 1 2 2  
P2 3 0 2 6 0 0  
P3 2 1 1 0 1 1  
P4 0 0 2 4 3 1  

首先,進入算法第一步,初始化。
那么Work = Available = [3 3 2]

1、首先看P0:P0的Need為[7 4 3],Available不能滿足,於是跳過去

2、P1的Need為[1 2 2]可以滿足,我們令Work = Allocation[P1] + Work,此時Work = [5 3 2]

3、再看P2,P2的Need為[6 0 0],那么現有資源不滿足。跳過去。

4、看P3,那么看P3,Work可以滿足。那么令Work = Allocation[P3] + Work,此時Work = [7 4 3]

5、再看P4,Work可以滿足。令Work = Allocation[P4] + Work ,此時Work = [7 4 5]。

到此第一輪循環完畢,由於找到了可用進程,那么進入第二輪循環。

6、看P0,Work此時可以滿足。令Work = Allocation[P0] + Work ,此時Work = [7 5 5]

7、再看P2,此時Work可以滿足P2。令Work = Allocation[P2] + Work , 此時Work = [10 5 7]

至此,算法運行完畢。找到安全序列<p1,p3,p4,p0,p2>,證明此時沒有死鎖危險。(安全序列未必唯一)。(僅是安全的序列)


資源請求算法

之前說完了怎么判定當前情況是否安全,下面就是說當有進程新申請資源的時候如何處理。
我們將第i個進程請求的資源數記為Requests[i](此進程是原來就知道的進程,是在安全序列里面的。若新加入一個進程,需要重新計算安全序列)

算法流程:

1.如果Requests[i]<=Need[i],則轉到第二步。否則,返回異常。這一步是控制進程申請的資源不得大於需要的資源

2.如果Requests[i]<=Available,則轉到第三步,否則Pi等待資源。

3.如果滿足前兩步,那么做如下操作:

Available = Available -Requests[i]
Allocation = Allocation[i]+Requests[i]
Need[i]=Need[i]-Requests[i]
調用安全判定算法,檢查是否安全。
if(安全)
{
    申請成功,資源分配
}
else
{
    申請失敗,資源撤回。第三步前幾個操作進行逆操作
}

缺點:很少有進程在運行前就知道其申請資源大小,而且進程數目不一定固定。所以這個比較適合那種變化不大的應用場景,局限性比較大。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM