linux互斥鎖和條件變數

2021-05-26 18:57:30 字數 3483 閱讀 5350

一、互斥鎖

1. 初始化:

在linux下, 執行緒的互斥量資料型別是pthread_mutex_t. 在使用前, 要對它進行初始化:

對於靜態分配的互斥量, 可以把它設定為pthread_mutex_initializer, 或者呼叫pthread_mutex_init.

對於動態分配的互斥量, 在申請記憶體(malloc)之後, 通過pthread_mutex_init進行初始化, 並且在釋放記憶體(free)前需要呼叫pthread_mutex_destroy.

原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric attr); 

int pthread_mutex_destroy(pthread_mutex_t *mutex);

返回值: 成功則返回0, 出錯則返回錯誤編號.

說明: 如果使用預設的屬性初始化互斥量, 只需把attr設為null

2. 互斥操作:

對共享資源的訪問, 要對互斥量進行加鎖, 如果互斥量已經上了鎖, 呼叫執行緒會阻塞, 直到互斥量被解鎖. 在完成了對共享資源的訪問後, 要對互斥量進行解鎖.

加鎖函式:

原型:int pthread_mutex_lock(pthread_mutex_t *mutex); 

int pthread_mutex_trylock(pthread_mutex_t *mutex); 

返回值: 成功則返回0, 出錯則返回錯誤編號. 

說明: 具體說一下trylock函式, 這個函式是非阻塞呼叫模式, 也就是說, 如果互斥量沒被鎖住, trylock函式將把互斥量加鎖, 並獲得對共享資源的訪問許可權; 如果互斥量被鎖住了, trylock函式將不會阻塞等待而直接返回ebusy, 表示共享資源處於忙狀態.

解鎖函式: 

原型:int pthread_mutex_unlock(pthread_mutex_t *mutex);

返回值: 成功則返回0, 出錯則返回錯誤編號.

3. 死鎖:

死鎖主要發生在有多個依賴鎖存在時, 會在乙個執行緒試圖以與另乙個執行緒相反順序鎖住互斥量時發生. 如何避免死鎖是使用互斥量應該格外注意的東西.

總體來講, 有幾個基本原則:

對共享資源操作前一定要獲得鎖.

完成操作以後一定要釋放鎖.

盡量短時間地占用鎖.

如果有多鎖, 如獲得順序是abc連環扣, 釋放順序也應該是abc.

執行緒錯誤返回時應該釋放它所獲得的鎖.

二、條件變數

條件變數是利用執行緒間共享的全域性變數進行同步的一種機制,主要包括兩個動作:乙個執行緒等待"條件變數的條件成立"而掛起;另乙個執行緒使"條件成立"(給出條件成立訊號)。為了防止競爭,條件變數的使用總是和乙個互斥鎖結合在一起。  

1.   建立和登出

條件變數和互斥鎖一樣,都有靜態動態兩種建立方式,靜態方式使用pthread_cond_initializer常量,如下:    

pthread_cond_t   cond=pthread_cond_initializer    

動態方式呼叫pthread_cond_init()函式,api定義如下:    

int   pthread_cond_init(pthread_cond_t   *cond,   pthread_condattr_t   *cond_attr)    

儘管posix標準中為條件變數定義了屬性,但在linuxthreads中沒有實現,因此cond_attr值通常為null,且被忽略。  

登出乙個條件變數需要呼叫pthread_cond_destroy(),只有在沒有執行緒在該條件變數上等待的時候才能登出這個條件變數,否則返回ebusy。因為linux實現的條件變數沒有分配什麼資源,所以登出動作只包括檢查是否有等待執行緒。api定義如下:    

int   pthread_cond_destroy(pthread_cond_t   *cond)        

2.   等待

int   pthread_cond_wait(pthread_cond_t   *cond,   pthread_mutex_t   *mutex)

int   pthread_cond_timedwait(pthread_cond_t   *cond,   pthread_mutex_t   *mutex,   const   struct   timespec   *abstime)

等待條件有兩種方式:無條件等待pthread_cond_wait()和計時等待pthread_cond_timedwait(),其中計時等待方式如果在給定時刻前條件沒有滿足,則返回etimeout,結束等待,其中abstime以與time()系統呼叫相同意義的絕對時間形式出現,0表示格林尼治時間2023年1月1日0時0分0秒。  

pthread_cond_wait會先解除之前的pthread_mutex_lock鎖定的mtx,然後阻塞在等待對列裡休眠,直到再次被喚醒(大多數情況下是等待的條件成立而被喚醒,喚醒後,該程序會先鎖定先pthread_mutex_lock(&mtx);,再讀取資源。

3.   激發

激發條件有兩種形式,pthread_cond_signal()啟用乙個等待該條件的執行緒,存在多個等待執行緒時按入隊順序啟用其中乙個;而pthread_cond_broadcast()則啟用所有等待執行緒。 

pthread_cond_wait() 將執行最後乙個操作:重新鎖定 mymutex。一旦 pthread_cond_wait() 鎖定了互斥物件,那麼它將返回並允許 1 號執行緒繼續執行。那時,它可以馬上檢查列表,檢視它所感興趣的更改。

讓我們先來回顧一下。第乙個執行緒首先呼叫:

pthread_mutex_lock(&mymutex);

然後,它檢查了列表。沒有找到感興趣的東西,於是它呼叫:

pthread_cond_wait(&mycond, &mymutex);

然後,pthread_cond_wait() 呼叫在返回前執行許多操作:

pthread_mutex_unlock(&mymutex);

它對 mymutex 解鎖,然後進入睡眠狀態,等待 mycond 以接收 posix 執行緒「訊號」。一旦接收到「訊號」(加引號是因為我們並不是在討論傳統的 unix 訊號,而是來自 pthread_cond_signal() 或 pthread_cond_broadcast() 呼叫的訊號),它就會甦醒。但 pthread_cond_wait() 沒有立即返回 -- 它還要做一件事:重新鎖定 mutex:

pthread_mutex_lock(&mymutex);

pthread_cond_wait() 知道我們在查詢 mymutex 「背後」的變化,因此它繼續操作,為我們鎖定互斥物件,然後才返回。

Linux互斥鎖和條件變數

include class thread lock thread lock void lock void unlock void wait void signal private pthread mutex t m mutex pthread mutexattr t m mutexatr pthre...

互斥鎖和條件變數

互斥瑣 定義 指代相互排斥,最基本的同步形式。用於保護臨界區,以保證任何時刻只有乙個執行緒或乙個程序在執行其中的 上鎖 pthread mutex lock 臨界區解鎖 pthread mutex unlock 條件變數 定義 用於等待訊號,同步的另一種手段。每乙個條件變數總有乙個互斥瑣與之關聯。等...

互斥鎖和條件變數

mutex體現的是一種競爭,我離開了,通知你進來。cond體現的是一種協作,我準備好了,通知你開始吧。互斥鎖乙個明顯的缺點是它只有兩種狀態 鎖定和非鎖定。而條件變數通過允許執行緒阻塞和等待另乙個執行緒傳送訊號的方法彌補了互斥鎖的不足,它常和互斥鎖一起配合使用。使用時,條件變數被用來阻塞乙個執行緒,當...