死鎖產生的原因以及避免死鎖的算法

一.死鎖的概念

在多道程序系統中,雖可藉助於多個進程的併發執行,來改善系統的資源利用率,提高系統的吞吐量,但可能發生一種危險━━死鎖。所謂死鎖(Deadlock),是指多個進程在運行中因爭奪資源而造成的一種僵局(Deadly_Embrace),當進程處於這種僵持狀態時,若無外力作用,它們都將無法再向前推進。一組進程中,每個進程都無限等待被該組進程中另一進程所佔有的資源,因而永遠無法得到的資源,這種現象稱爲進程死鎖,這一組進程就稱爲死鎖進程。

二.死鎖產生的原因

  • 產生死鎖的原因主要是:
    (1) 因爲系統資源不足。
    (2) 進程運行推進的順序不合適。
    (3) 資源分配不當等。
    如果系統資源充足,進程的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則就會因爭奪有限的資源而陷入死鎖。其次,進程運行推進順序與速度不同,也可能產生死鎖。

  • 產生死鎖的四個必要條件:
    (1) 互斥條件:一個資源每次只能被一個進程使用。
    (2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
    (3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
    (4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。


這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。


  • 死鎖的解除與預防:
    理解了死鎖的原因,尤其是產生死鎖的四個必要條件,就可以最大可能地避免、預防和解除死鎖。所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確定資源的合理分配算法,避免進程永久佔據系統資源。此外,也要防止進程在處於等待狀態的情況下佔用資源。因此,對資源的分配要給予合理的規劃。

二.數據結構設計

(一)可利用資源向量矩陣AVAILABLE。這是一個含有m個元素的數組,其中的每一個元素代表一類可利用的資源數目,其初始值是系統中所配置的該類全部可用資源的數目,其數值隨該類資源的分配和回收而動態地改變。如果AVAILABLE [j]= K,則表示系統中現有R類資源K個
(二)最大需求矩陣MAX。這是一個n*m的矩陣,用以表示每一個進程對m類資源的最大需求。如果MAX =K,則表示進程i需要R類資源的數目爲K。
(三)分配矩陣ALLOCATION。這也是一個n*m的矩陣,它定義了系統中每一類資源當前已分配給每一進程的資源數。如果ALLOCATION =K,則表示進程i當前已分得R類資源的數目爲K。 (四)需求矩陣NEED。這也是一個n*m的矩陣,用以表示每一個進程尚需的各類資源數。如果NEED =K,則表示進程i還需要R類資源K個,才能完成其任務。 上述矩陣存在下述關係: NEED = MAX-ALLOCATION

三.算法實現

(一) 初始化 由用戶輸入數據,分別對可利用資源向量矩陣AVAILABLE、最大需求矩陣MAX、分配矩陣ALLOCATION、需求矩陣NEED賦值。
(二)銀行家算法 在避免死鎖的方法中,所施加的限制條件較弱,有可能獲得令人滿意的系統性能。在該方法中把系統的狀態分爲安全狀態和不安全狀態,只要能使系統始終都處於安全狀態,便可以避免發生死鎖。 銀行家算法的基本思想是分配資源之前,判斷系統是否是安全的;若是,才分配。它是最具有代表性的避免死鎖的算法。 設進程cusneed提出請求REQUEST ,則銀行家算法按如下規則進行判斷。
(1)如果REQUEST [cusneed] <= NEED[cusneed],則轉(2);否則,出錯。
(2)如果REQUEST [cusneed] <= AVAILABLE[cusneed],則轉(3);否則,出錯。 (3)系統試探分配資源,修改相關數據:
AVAILABLE-=REQUEST[cusneed]; ALLOCATION[cusneed]+=REQUEST[cusneed];
NEED[cusneed]-=REQUEST[cusneed];
(4)系統執行安全性檢查,如安全,則分配成立;否則試探險性分配作廢,系統恢復原狀,進程等待。
(三)安全性檢查算法
(1)設置兩個工作向量Work=AVAILABLE;FINISH
(2)從進程集合中找到一個滿足下述條件的進程,
FINISH==false;
NEED<=Work;
如找到,執行(3);否則,執行(4)
(3)設進程獲得資源,可順利執行,直至完成,從而釋放資源。 Work+=ALLOCATION; Finish=true; GOTO 2
(4)如所有的進程Finish= true,則表示安全;否則系統不安全。

四.源程序清單

#include <iostream> using namespace std; 
#define MAXPROCESS 50                         /*最大進程數*/
#define MAXRESOURCE 100                         /*最大資源數*/  
int AVAILABLE[MAXRESOURCE];                     /*可用資源數組*/  
int MAX[MAXPROCESS][MAXRESOURCE];             /*最大需求矩陣*/ 
int ALLOCATION[MAXPROCESS][MAXRESOURCE];     /*分配矩陣*/ 
int NEED[MAXPROCESS][MAXRESOURCE];             /*需求矩陣*/  
int REQUEST[MAXPROCESS][MAXRESOURCE];         /*進程需要資源數*/ 
bool FINISH[MAXPROCESS];                         /*系統是否有足夠的資源分配*/ 
int p[MAXPROCESS];                             /*記錄序列*/
int m,n;                                     /*m個進程,n個資源*/ void Init(); bool Safe(); void Bank(); int main() 
{       
    Init();      
    Safe();      
    Bank(); 
}  
void Init()                 /*初始化算法*/
{       
    int i,j;           
    cout<<"請輸入進程的數目:";      
    cin>>m;       
    cout<<"請輸入資源的種類:";      
    cin>>n;       
    cout<<"請輸入每個進程最多所需的各資源數,按照"<<m<<"x"<<n<<"矩陣輸入"<<endl;      
    for(i=0;i<m;i++)      
        for(j=0;j<n;j++)      
            cin>>MAX[j];       
    cout<<"請輸入每個進程已分配的各資源數,也按照"<<m<<"x"<<n<<"矩陣輸入"<<endl;      for(i=0;i<m;i++)
    {           
        for(j=0;j<n;j++)
        {
            cin>>ALLOCATION[j];
            NEED[j]=MAX[j]-ALLOCATION[j];
            if(NEED[j]<0)              
            {                   
                cout<<"您輸入的第"<<i+1<<"個進程所擁有的第"<<j+1<<"個資源數錯誤,請重新輸入:"<<endl;
                j--;
                continue;
            }          
        }      
    }       
    cout<<"請輸入各個資源現有的數目:"<<endl;
    for(i=0;i<n;i++)      
    {           
        cin>>AVAILABLE;
    } 
}  
void Bank()                 /*銀行家算法*/ 
{
    int i,cusneed;
    char again;
    while(1)
    {
        cout<<"請輸入要申請資源的進程號(注:第1個進程號爲0,依次類推)"<<endl;
        cin>>cusneed;
        cout<<"請輸入進程所請求的各資源的數量"<<endl;
        for(i=0;i<n;i++)
        {
            cin>>REQUEST[cusneed];
        }
        for(i=0;i<n;i++)
        {
            if(REQUEST[cusneed]>NEED[cusneed])
            {
                cout<<"您輸入的請求數超過進程的需求量!請重新輸入!"<<endl;
                continue;
            }
            if(REQUEST[cusneed]>AVAILABLE)
            {
                cout<<"您輸入的請求數超過系統有的資源數!請重新輸入!"<<endl;
                continue;
            }
        }
        for(i=0;i<n;i++)
        {
            AVAILABLE-=REQUEST[cusneed];
            ALLOCATION[cusneed]+=REQUEST[cusneed];
            NEED[cusneed]-=REQUEST[cusneed];
        }
        if(Safe())
        {
            cout<<"同意分配請求!"<<endl;
        }
        else
        {
            cout<<"您的請求被拒絕!"<<endl;
            for(i=0;i<n;i++)
            {
                AVAILABLE+=REQUEST[cusneed];
                ALLOCATION[cusneed]-=REQUEST[cusneed];
                NEED[cusneed]+=REQUEST[cusneed];
            }
        }
        for(i=0;i<m;i++)
        {
            FINISH=false;
        }
        cout<<"您還想再次請求分配嗎?是請按y/Y,否請按其它鍵"<<endl;
        cin>>again;
        if(again=='y'||again=='Y')
        {
            continue;
        }
        break;
    }
}
bool Safe()/*安全性算法*/ 
{
    int i,j,k,l=0;
    int Work[MAXRESOURCE];/*工作數組*/
    for(i=0;i<n;i++)
        Work=AVAILABLE;
    for(i=0;i<m;i++)
    {
        FINISH=false;
    }
    for(i=0;i<m;i++)
    {
        if(FINISH==true)
        {
            continue;
        }
        else
        {
            for(j=0;j<n;j++)
            {
                if(NEED[j]>Work[j])
                {
                    break;
                }
            }
            if(j==n)
            {
                FINISH=true;
                for(k=0;k<n;k++)
                {
                    Work[k]+=ALLOCATION[k];
                }
                p[l++]=i;
                i=-1;
            }
            else
            {
                continue;
            }
        }
        if(l==m)
        {
            cout<<"系統是安全的"<<endl;
            cout<<"安全序列:"<<endl;
            for(i=0;i<l;i++)
            {
                cout<<p;
                if(i!=l-1)
                {
                    cout<<"-->";
                }
            }
            cout<<""<<endl;
            return true;
        }
    }
    cout<<"系統是不安全的"<<endl;
    return false;
}

五.實驗分析:

(1)下列狀態是否安全?(三個進程共享12個同類資源) 進程 已分配資源數 最大需求數
1 1 4 (狀態a)
2 4 4
3 5 8
1 1 4 (狀態b)
2 4 6
3 6 8
狀態a安全,序列爲:2–>1–> 3
狀態b不安全,只剩1個可用資源,收不回已分配資源。
(2)考慮下列系統狀態

分配矩陣 最大需求矩陣 可用資源矩陣
0 0 1 2 0 0 1 2 1 5 2 0
1 0 0 0 1 7 5 0
1 3 5 4 2 3 5 6
0 6 3 2 0 6 5 2
0 0 1 4 0 6 5 6

問系統是否安全?若安全就給出所有的安全序列。若進程2請求(0420),可否立即分配?
答:安全。安全序列爲:1–>3–>2–>5–>4。 若進程2請求(0420),可立即分配。分配後可用資源爲1 1 0 0,回收1進程資源, 可用資源數爲:1 1 1 2,然後執行3–>2–>5–>4序列。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章