LINUX 互斥鎖 學習

2021-10-14 04:12:21 字數 4699 閱讀 4567

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...