posix下抽象了乙個鎖型別的結構:ptread_mutex_t。通過對該結構的操作,來判斷資源是否可以訪問。顧名思義,加鎖(lock)後,別人就無法開啟,只有當鎖沒有關閉(unlock)的時候才能訪問資源。
即物件互斥鎖的概念,來保證共享資料操作的完整性。每個物件都對應於乙個可稱為" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有乙個執行緒訪問該物件。
使用互斥鎖(互斥)可以使執行緒按順序執行。通常,互斥鎖通過確保一次只有乙個執行緒執行**的臨界段來同步多個執行緒。互斥鎖還可以保護單執行緒**。
要更改預設的互斥鎖屬性,可以對屬性物件進行宣告和初始化。通常,互斥鎖屬性會設定在應用程式開頭的某個位置,以便可以快速查詢和輕鬆修改。
l 標頭檔案:
#include
l 函式原型:
int pthread_mutex_init(pthread_mutex_t*restrict mutex,constpthread_mutexattr_t*restrict attr);
pthread_mutex_tmutex =pthread_mutex_initializer;
l 函式作用:
該函式用於c函式的多執行緒程式設計中,互斥鎖的初始化。
pthread_mutex_init() 函式是以動態方式建立互斥鎖的,引數attr指定了新建互斥鎖的屬性。如果引數attr為空(null),則使用預設的互斥鎖屬性,預設屬性為快速互斥鎖 。互斥鎖的屬性在建立鎖的時候指定,在linuxthreads實現中僅有乙個鎖型別屬性,不同的鎖型別在試圖對乙個已經被鎖定的互斥鎖加鎖時表現不同。
pthread_mutexattr_init() 函式成功完成之後會返回零,其他任何返回值都表示出現了錯誤。函式成功執行後,互斥鎖被初始化為未鎖住態。
pthread_mutexattr_settype(); 用於設定互斥鎖屬性
l 互斥鎖pthread_mutex_t的使用:
1. 互斥鎖建立和銷毀
有兩種方法建立互斥鎖,靜態方式和動態方式。posix定義了乙個巨集pthread_mutex_initializer來靜態初始化互斥鎖,方法如下:
pthread_mutex_tmutex=pthread_mutex_initializer;
在linuxthreads實現中,pthread_mutex_t是乙個結構,而pthread_mutex_initializer則是乙個結構常量。
動態方式是採用pthread_mutex_init()函式來初始化互斥鎖,api定義如下:
intpthread_mutex_init(pthread_mutex_t*mutex, constpthread_mutexattr_t*mutexattr)
其中mutexattr用於指定互斥鎖屬性(見下),如果為null則使用預設屬性。
pthread_mutex_destroy()用於登出乙個互斥鎖,api定義如下:
intpthread_mutex_destroy(pthread_mutex_t*mutex)
銷毀乙個互斥鎖即意味著釋放它所占用的資源,且要求鎖當前處於開放狀態。由於在linux中,互斥鎖並不占用任何資源,因此linuxthreads中的 pthread_mutex_destroy()除了檢查鎖狀態以外(鎖定狀態則返回ebusy)沒有其他動作。
pthread_mutexattr_destroy 銷毀乙個設定互斥鎖屬性值
2.互斥鎖屬性
互斥鎖的屬性在建立鎖的時候指定,在linuxthreads實現中僅有乙個鎖型別屬性,不同的鎖型別在試圖對乙個已經被鎖定的互斥鎖加鎖時表現不同。當前(glibc2.2.3,linuxthreads0.9)有四個值可供選擇:
* pthread_mutex_timed_np,這是預設值,也就是普通鎖。當乙個執行緒加鎖以後,其餘請求鎖的執行緒將形成乙個等待佇列,並在解鎖後按優先順序獲得鎖。這種鎖策略保證了資源分配的公平性。
* pthread_mutex_recursive_np,巢狀鎖,允許同乙個執行緒對同乙個鎖成功獲得多次,並通過多次unlock解鎖。如果是不同執行緒請求,則在加鎖執行緒解鎖時重新競爭。
* pthread_mutex_errorcheck_np,檢錯鎖,如果同乙個執行緒請求同乙個鎖,則返回edeadlk,否則與pthread_mutex_timed_np型別動作相同。這樣保證當不允許多次加鎖時不出現最簡單情況下的死鎖。
* pthread_mutex_adaptive_np,適應鎖,動作最簡單的鎖型別,僅等待解鎖後重新競爭。
3.其他鎖操作
鎖操作主要包括加鎖pthread_mutex_lock()、解鎖pthread_mutex_unlock()和測試加鎖 pthread_mutex_trylock()三個,不論哪種型別的鎖,都不可能被兩個不同的執行緒同時得到,而必須等待解鎖。對於普通鎖和適應鎖型別,解鎖者可以是同程序內任何執行緒;而檢錯鎖則必須由加鎖者解鎖才有效,否則返回eperm;對於巢狀鎖,文件和實現要求必須由加鎖者解鎖,但實驗結果表明並沒有這種限制,這個不同目前還沒有得到解釋。在同一程序中的執行緒,如果加鎖後沒有解鎖,則任何其他執行緒都無法再獲得鎖。
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
pthread_mutex_trylock()語義與pthread_mutex_lock()類似,不同的是在鎖已經被佔據時返回ebusy而不是掛起等待。
4.死鎖
死鎖主要發生在有多個依賴鎖存在時, 會在乙個執行緒試圖以與另乙個執行緒相反順序鎖住互斥量時發生. 如何避免死鎖是使用互斥量應該格外注意的東西。
總體來講, 有幾個不成文的基本原則:
對共享資源操作前一定要獲得鎖。
完成操作以後一定要釋放鎖。
盡量短時間地占用鎖。
如果有多鎖, 如獲得順序是abc連環扣, 釋放順序也應該是abc。
執行緒錯誤返回時應該釋放它所獲得的鎖。
下面是一段測試**,建立兩個執行緒,分別訪問全域性變數gnum,並且修改它,列印出來.
static int inline my_mutex_init(pthread_mutex_t *pmutex)
1 /* mutex.c */
2 #include 3 #include 4 #include 5 #include 6
7 /* 全域性變數 */
8 int gnum = 0;
9 /* 互斥量 */
10 pthread_mutex_t mutex;
11 12 /* 宣告執行緒執行服務程式. */
13 static void pthread_func_1(void);
14 static void pthread_func_2(void);
15 16 int main (void)
17 34
35 ret = pthread_create(&pt_2, //執行緒識別符號指標
36 null, //預設屬性
37 (void *)pthread_func_2, //執行函式
38 null); //無引數
39 if (ret != 0)
40
43 /*等待執行緒1、2的結束*/
44 pthread_join(pt_1, null);
45 pthread_join(pt_2, null);
46 47 printf ("main programme exit!/n");
48 return 0;
49 }
50 51 /*執行緒1的服務程式*/
52 static void pthread_func_1(void)
53 66
67 pthread_exit(null);
68 }
69 70 /*執行緒2的服務程式*/
71 static void pthread_func_2(void)
72 85
86 pthread_exit (null);
87 }
linux執行緒互斥鎖
使用執行緒編寫程式需要技巧,而多執行緒的程式中的bug非常難以跟蹤 除錯,因為這些bug經常是難以再現的。競爭條件 當乙個執行緒訪問乙個資料結構的時候,另乙個執行緒也訪問同乙個資料結構,這時就出現了競爭條件 兩個執行緒 也可能是多個 競爭對同乙個資源的訪問。當其中乙個執行緒處理到一部分的時候,另外的...
linux 執行緒互斥鎖
一,鎖的建立 鎖可以被動態或靜態建立,可以用巨集pthread mutex initializer來靜態的初始化鎖,採用這種方式比較容易理解,互斥鎖是pthread mutex t的結構體,而這個巨集是乙個結構常量,如下可以完成靜態的初始化鎖 pthread mutex t mutex pthrea...
Linux執行緒互斥鎖
一,鎖的建立 鎖可以被動態或靜態建立,可以用巨集pthread mutex initializer來靜態的初始化鎖,採用這種方式比較容易理解,互斥鎖是pthread mutex t的結構體,而這個巨集是乙個結構常量,如下可以完成靜態的初始化鎖 pthread mutex t mutex pthrea...