互斥鎖:
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
中的釋放鎖操作同樣只用一條指令實現,以保證它的原子性。
5、例:如下**:
原本count全域性變數+1,加5000次,但是兩個執行緒理應加到10000才正確,但是因為count不是原子性,導致出錯;
我們要清楚乙個增量操作分為三步驟:
1)從記憶體當中讀入暫存器
2)暫存器進行增量操作
3)寫回記憶體
正因為這三步操作,所以當不同步的時候,第乙個執行緒已經對增量操作了,但是第二個執行緒讀取到的依然是第乙個執行緒增量操作之前的內容。這樣就會出現問題,本來應該由1增加到3的,結果變為了由1到2。
要想**按照我們預期的想法加到10000,必須加互斥鎖,保護臨界資源:修改上**如下:
#include#include#include#include#includeint count = 0;
pthread_mutex_t lock = pthread_mutex_initializer;
void* pthread_run()
// sleep(200);
//return (void*)5;
}int main()
新增互斥鎖保證其原子性,結果正確:
死鎖:
1、什麼是死鎖:
所謂死鎖是指多個執行緒因競爭資源而造成的一種僵局(互相等待),若無外力作用,這些執行緒都將無法向前推進的一種行為。
一般情況下,如果同乙個執行緒先後兩次呼叫
lock
,在第二次呼叫時,由於鎖已經被占用,該執行緒會
掛起等待別的執行緒釋放鎖,然而鎖正是被自己占用著的,該執行緒又被掛起而沒有機會釋放鎖,因此
就永遠處於掛起等待狀態了(乙個資源程式比較長開始使用了這把鎖,中途忘記這把鎖被使用,再次上鎖;或者在這個資源程式中呼叫其他函式也使用了這把鎖)
另一種:若執行緒a
獲得了鎖
1,執行緒
b獲得了鎖
2,這時執行緒a呼叫
lock
試圖獲得鎖
2,結果是需要掛起等待執行緒b釋放
鎖2,而這時執行緒
b也呼叫
lock
試圖獲得鎖
1,結果是需要掛起等待執行緒
a釋放鎖
1,於是執行緒a和
b都永遠處於掛起狀態了。
2、死鎖產生的四個必要條件:
(1) 互斥條件:乙個資源每次只能被乙個程序使用
(2) 請求與保持條件:乙個程序因請求資源而阻塞時,對已獲得的資源保持不放。
(3) 不剝奪條件:程序已獲得的資源,在末使用完之前,不能強行剝奪。
(4) 迴圈等待條件:若干程序之間形成一種頭尾相接的迴圈等待資源關係。
這四個條件是死鎖的必要條件
,只要系統發生死鎖,這些條件必然成立,而只要上述條件之
一不滿足,就不會發生死鎖。
3、如何避免死鎖:
預防死鎖:
資源一次性分配:(破壞請求和保持條件)
可剝奪資源:即當某程序新的資源未滿足時,釋放已占有的資源(破壞不可剝奪條件)
資源有序分配法:系統給每類資源賦予乙個編號,每乙個程序按編號遞增的順序請求資源,釋放則相反(破壞環路等待條件)
避免死鎖:
預防死鎖的幾種策略,會嚴重地損害系統效能。因此在避免死鎖時,要施加較弱的限制,從而獲得 較滿意的系統效能。由於在避免死鎖的策略中,允許程序動態地申請資源。因而,系統在進行資源分配之前預先計算資源分配的安全性。若此次分配不會導致系統進入不安全狀態,則將資源分配給程序;否則,程序等待。其中最具有代表性的避免死鎖演算法是銀行家演算法。
檢測死鎖
首先為每個程序和每個資源指定乙個唯一的號碼;
然後建立資源分配表和程序等待表,例如:
解除死鎖:
當發現有程序死鎖後,便應立即把它從死鎖狀態中解脫出來,常採用的方法有:
剝奪資源:從其它程序剝奪足夠數量的資源給死鎖程序,以解除死鎖狀態;
撤消程序:可以直接撤消死鎖程序或撤消代價最小的程序,直至有足夠的資源可用,死鎖狀態.消除為止;所謂代價是指優先順序、執行代價、程序的重要性和價值等。
執行緒互斥鎖與死鎖
1 首先來了解執行緒的同步與互斥 當多個執行緒訪問同乙個程序時的臨界區時需要被同步與互斥保護避免產生衝突。比如當兩個執行緒都要把某個全域性變數增加1,這個操作在某平台上需要三條指令完成 1,從記憶體讀變數到暫存器。2,暫存器的值加1。3,將暫存器的值寫回記憶體。來看這個程式 2 互斥鎖 先來看mut...
互斥鎖 死鎖與執行緒安全
一 典型的兩種死鎖情形 一 執行緒自己將自己鎖住 一般情況下,如果同乙個執行緒先後兩次呼叫lock,在第二次調 用時,由於鎖已經被占用,該執行緒會掛起等待占用鎖的執行緒釋放鎖,然而鎖正是被自己占用著的,該執行緒又被掛起而沒有機會釋放鎖,因此 就永遠處於掛起等待狀態了,於是就形成了死鎖 deadloc...
執行緒之互斥鎖
在乙個多執行緒的程式中,有時需要同時對共享資源的訪問,就會造成對共享資源的讀寫問題。例如 有五個執行緒,其中乙個對共享資源進行修改,其餘四個執行緒需要同時對共享資源進行讀訪問。勢必會造成其餘四個執行緒讀取資料的不穩定。此時就可以使用互斥鎖去解決這一問題。當修改共享資源的執行緒需要對資料進行修改時,首...