死鎖的條件、原因以及場景分析


死鎖可以稱為進程死鎖。那么是在多進程(並發)情況下可能會出現的。

指的是多個進程因為競爭資源而造成的僵局(互相等待),沒有外力,那么所有進程都會無法向前推進。

所以是在操作系統和並發程序設計中需要特別考慮的問題。

因此,可以可以得出如下的場景和必備條件。

場景:

  • 系統資源的競爭。只有資源不足時才會出現死鎖可能,另外,可剝奪資源的競爭是不會引發死鎖的;
  • 進程推進順序不對。多進程在運行時,請求和釋放資源的順序不當。
  • 系統資源分配不當。

四大必要條件:

  • 互斥:進程對分配到的資源排它性使用。獨占資源,是由資源本身的屬性決定的。
  • 請求和保持:保持已有資源,同時請求新的資源,在請求過程中以及因為沒有得到新資源而阻塞,已有資源仍然保持;
  • 不可剝奪:進程已有的資源在使用完之前不能被剝奪,只能自己釋放;
  • 環路等待:必然存在一個進程資源環形請求鏈。

死鎖預防:打破之前四個條件

  • 打破互斥在實際中應用不大;
  • 打破請求與保持,可以實行資源預先分配策略,即進程在運行前一次性申請所需要的全部資源,如果不能滿足,則暫不運行。實際應用中,進程在執行時是動態的,不可預測的,並且資源利用率低,降低了進程並發性。
  • 打破不可剝奪,當請求新資源不能滿足,需要釋放已有資源,系統性能受到很大降低
  • 打破循環等待:實行資源有序分配策略。可以將資源事先分類編號,按號分配,使進程在申請、占用資源是不會形成環路。所有進程對資源的請求必須嚴格按資源序號遞增的順序提出。但是也有問題,合理編號困難,增大系統開銷,另外也增加了進程對資源的占有時間。

死鎖避免:

  不限制進程有關申請資源的命令,而是對進程所發出的每一個申請資源命令加以動態地檢查,並根據檢查結果決定是否進行資源分配。就是說,在資源分配過程中若預測有發生死鎖的可能性,則加以避免。這種方法的關鍵是確定資源分配的安全性。

  銀行家算法(1968年):允許進程動態地申請資源,系統在每次實施資源分配之前,先計算資源分配的安全性,若此次資源分配安全(即資源分配后,系統能按某種順序來為每個進程分配其所需的資源,直至最大需求,使每個進程都可以順利地完成),便將資源分配給進程,否則不分配資源,讓進程等待。

死鎖檢測與修復:

  預防和避免的手段達到排除死鎖的目的是很困難的。一種簡便的方法是系統為進程分配資源時,不采取任何限制性措施,但是提供了檢測和解脫死鎖的手段:能發現死鎖並從死鎖狀態中恢復出來。因此,在實際的操作系統中往往采用死鎖的檢測與恢復方法來排除死鎖。

----------------------------------------------------------------------------------------------------

死鎖常見的場景如下:

忘記釋放鎖:

void data_process()
{
    EnterCriticalSection();

    if(/* error happens, forget LeaveCriticalSection */)
        return;

    LeaveCriticalSection();
}

  

單線程重復申請鎖(所以單線程的時候也有可能進入死鎖)

void sub_func()
{
    EnterCriticalSection();
    do_something();
    LeaveCriticalSection();
}

void data_process()
{
    EnterCriticalSection();
    sub_func();
    LeaveCriticalSection();
}

  

多線程多鎖申請

void data_process1()
{
    EnterCriticalSection(&cs1);  // 申請鎖的順序有依賴
    EnterCriticalSection(&cs2);
    do_something1();
    LeaveCriticalSection(&cs2);
    LeaveCriticalSection(&cs1);
}

void data_process2()
{
    EnterCriticalSection(&cs2);  // 申請鎖的順序有依賴
    EnterCriticalSection(&cs1);
    do_something2();
    LeaveCriticalSection(&cs1);
    LeaveCriticalSection(&cs2);
}

  

多線程環形鎖

 

編程中如何來避免:

  • 檢查有沒有忘記釋放鎖
  • 如果自己模塊可能重復使用一個鎖,建議使用嵌套鎖
  • 建議使用庫里面的鎖
  • 如果某項業務需要獲取多個鎖,保證鎖按某種順序來獲取
  • 編寫簡單測試用例驗證是否存在死鎖

 

參考:https://www.cnblogs.com/kuliuheng/p/4071555.html


免責聲明!

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



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