一、互斥鎖:
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) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。
三、如何預防、避免、解除死鎖:
-
預防死鎖:
資源一次性分配:(破壞請求和保持條件)
可剝奪資源:即當某進程新的資源未滿足時,釋放已佔有的資源(破壞不可剝奪條件)
資源有序分配法:系統給每類資源賦予一個編號,每一個進程按編號遞增的順序請求資源,釋放則相反(破壞環路等待條件)
-
避免死鎖:
預防死鎖的幾種策略,會嚴重地損害系統性能。因此在避免死鎖時,要施加較弱的限制,從而獲得 較滿意的系統性能。由於在避免死鎖的策略中,允許進程動態地申請資源。因而,系統在進行資源分配之前預先計算資源分配的安全性。若此次分配不會導致系統進入不安全狀態,則將資源分配給進程;否則,進程等待。其中最具有代表性的避免死鎖算法是銀行家算法。
-
檢測死鎖
首先爲每個進程和每個資源指定一個唯一的號碼;
然後建立資源分配表和進程等待表,例如:
-
解除死鎖:
當發現有進程死鎖後,便應立即把它從死鎖狀態中解脫出來,常採用的方法有:
剝奪資源:從其它進程剝奪足夠數量的資源給死鎖進程,以解除死鎖狀態;
撤消進程:可以直接撤消死鎖進程或撤消代價最小的進程,直至有足夠的資源可用,死鎖狀態.消除爲止;所謂代價是指優先級、運行代價、進程的重要性和價值等。