linux下為了多執行緒同步,通常用到鎖的概念。
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() 函式成功完成之後會返回零,其他任何返回值都表示出現了錯誤。
函式成功執行後,互斥鎖被初始化為未鎖住態。
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)沒有其他動作。
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,並且修改它,列印出來.
/* mutex.c */
#include #include #include #include /* 全域性變數 */
int gnum = 0;
/* 互斥量 */
pthread_mutex_t mutex;
/* 宣告執行緒執行服務程式. */
static void pthread_func_1(void);
static void pthread_func_2(void);
int main (void)
ret = pthread_create(&pt_2, //執行緒識別符號指標
null, //預設屬性
(void *)pthread_func_2, //執行函式
null); //無引數
if (ret != 0)
/*等待執行緒1、2的結束*/
pthread_join(pt_1, null);
pthread_join(pt_2, null);
printf ("main programme exit!/n");
return 0;
}/*執行緒1的服務程式*/
static void pthread_func_1(void)
pthread_exit(null);
}/*執行緒2的服務程式*/
static void pthread_func_2(void)
pthread_exit (null);
}
ngx process options函式詳解
ngx process options是初始化init cycle中的一些如 conf file,prefix,conf prefix等字段的功能,其方法的定義在src core nginx.c中,以下為詳細 主要功能是將ngx prefix,配置檔案的位置資訊,以及命令列引數的資訊初始化到cycl...
linux clock gettime函式詳解
注意 1.精確級別,納秒級別 原型long sys clock gettime clockid t which clock,struct timespec tp which clock引數解釋 clock realtime 系統實時時間,隨系統實時時間改變而改變,即從utc1970 1 1 0 0 ...
遞迴函式(詳例)
從函式棧的角度的運用 簡單的列印運用 includevoid function int n int main void function int n return 非空鍊錶的遞迴找最大值 lim findmax lim headptr 為了更好的理解遞迴的執行過程 在呼叫自生到最後時,if head...