互斥鎖、死鎖以及如何預防、避免、檢測、解除死鎖

一、互斥鎖:


1、互斥鎖基本原理:
     互斥鎖是一個二元變量,其狀態爲開鎖(允許0)和上鎖(禁止1),將某個共享資源與某個特定互斥鎖在邏輯上綁定(要申請該資源必須先獲取鎖)。
     (1)訪問公共資源前,必須申請該互斥鎖,若處於開鎖狀態,則申請到鎖對象,並立即佔有該鎖,以防止其他線程訪問該資源;如果該互斥鎖處於鎖定狀態,則阻塞當前線程。
     (2)只有鎖定該互斥鎖的進程才能釋放該互斥鎖,其他線程試圖釋放無效。
2、初始化互斥鎖:
     使用之前,需要定義互斥鎖,使用函數:pthread_mutex_t lock;進行定義。
     初始化鎖:
     extern int    pthread_mutex_init(pthread_mutex_t *_mutex,_const pthread_mutex_mutexattr_t* _mutexattr)
          第一個參數mutex指要初始化的互斥鎖的指針。
          第二個參數mutexattr是指向對象的指針,如果該屬性爲空,則使用默認的屬性。
          全用宏PTHREAD_MUTEX_INITIALIZER來初始化靜態分配的互斥鎖(全局鎖);
3、申請互斥鎖
     如果一個線程要佔用共享資源,必須先申請對應互斥鎖,使用函數:
extern int pthread_mutex_lock(pthread_mutex* _mutex)以阻塞方式申請互斥鎖;
extern int pthread_mutex_trylock(pthread_mutex* _mutex)以非阻塞方式申請互斥鎖;
    若申請成功,返回0,否則,返回一個錯誤編號。
     <注:參數都是要申請互斥鎖的指針>
4、釋放互斥鎖
     釋放互斥鎖用函數:
     extern int pthread_mutex_unlock(pthread_mutex_t* _mutex)
     參數mutex是指向要解鎖的互斥鎖的指針
     釋放只能由佔有該互斥鎖的線程完成,如果釋放成功,返回0,失敗返回錯誤編號。
     unlock中的釋放鎖操作同樣只用一條指令實現,以保證它的原

二、死鎖:

1、什麼是死鎖:

     一般情況下,如果同一個線程先後兩次調用lock,在第二次調用時,由於鎖已經被佔用,該線程會掛起等待別的線程釋放鎖,然而鎖正是被自己佔用着的,該線程又被掛起而沒有機會釋放鎖,因此就永遠處於掛起等待狀態了,這叫做死鎖(Deadlock)。
     另一種:若線程A獲得了鎖1,線程B獲得了鎖2,這時線程A調用lock試圖獲得鎖2,結果是需要掛起等待線程B釋放鎖2,而這時線程B也調用lock試圖獲得鎖1,結果是需要掛起等待線程A釋放鎖1,於是線程A和B都永遠處於掛起狀態了。

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


、如何預防、避免、解除死鎖:

 

  • 預防死鎖:

資源一次性分配:(破壞請求和保持條件)

可剝奪資源:即當某進程新的資源未滿足時,釋放已佔有的資源(破壞不可剝奪條件)

資源有序分配法:系統給每類資源賦予一個編號,每一個進程按編號遞增的順序請求資源,釋放則相反(破壞環路等待條件)

  • 避免死鎖:

預防死鎖的幾種策略,會嚴重地損害系統性能。因此在避免死鎖時,要施加較弱的限制,從而獲得 較滿意的系統性能。由於在避免死鎖的策略中,允許進程動態地申請資源。因而,系統在進行資源分配之前預先計算資源分配的安全性。若此次分配不會導致系統進入不安全狀態,則將資源分配給進程;否則,進程等待。其中最具有代表性的避免死鎖算法是銀行家算法。

  • 檢測死鎖

首先爲每個進程和每個資源指定一個唯一的號碼;

然後建立資源分配表和進程等待表,例如:

  • 解除死鎖:

當發現有進程死鎖後,便應立即把它從死鎖狀態中解脫出來,常採用的方法有:

剝奪資源:從其它進程剝奪足夠數量的資源給死鎖進程,以解除死鎖狀態;

撤消進程:可以直接撤消死鎖進程或撤消代價最小的進程,直至有足夠的資源可用,死鎖狀態.消除爲止;所謂代價是指優先級、運行代價、進程的重要性和價值等。
 

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