為什麼使用條件變數(condition variable)
想想我們怎麼實現下面的場景:
當執行緒a需要通知執行緒b某件事情已經準備好,我們該怎麼做?
我們通常的做法是:設定乙個全域性變數v,如果執行緒a已經準備好了某件事,則把v設定為1;執行緒b則不停得檢測v,直到v變為1再繼續下面的操作。這種做法的缺點是非常的浪費cpu,因為執行緒b需要不停的busy loop。
為了改善這種狀況,引入了條件變數,它允許乙個執行緒一直休眠,直到另乙個執行緒通知它某件事已經準備好了。順帶提一下,linux核心中有相似的機制semaphore.
條件變數是程式用來等待某個謂詞為真的機制,也是用來通知其他執行緒謂詞為真的機制。條件變數的作用是發訊號(訊號代表的具體內容由程式自己解釋),而不是互斥,因此程式需要提供乙個互斥量來同步對共享資料的訪問。
條件變數的初始化
靜態初始化
pthread_cond_t cond = pthread_cond_initializer
動態初始化
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
條件變數的銷毀
int pthread_cond_destroy(pthread_cond_t *cond)
條件變數的操作
int pthread_cond_signal(pthread_cond_t *cond)
int pthread_cond_broadcast(pthread_cond_t *cond)
注意點:
1.pthread_cond_signal()一次只喚醒乙個執行緒,而pthread_cond_broadcast()喚醒所有等待的執行緒。
2.條件變數只是乙個簡單的機制,如果在訊號發出後沒有執行緒等待在上面,那麼該訊號將會丟失。
3.注意pthread_cond_broadcast()呼叫後,等待執行緒要完成的工作
a) 所有的執行緒都將被喚醒
b) 首先有乙個執行緒被喚醒,該執行緒檢測共享變數的狀態,看是否有工作需要完成。完成相應的工作,改變共享變數的狀態—用來顯示該工作已經完成,釋放相應的鎖。
c) 剩下的執行緒依次的加鎖,檢測共享變數的狀態。因為第乙個執行緒已經改變了共享變數的狀態,這些執行緒發現沒有工作需要完成,解鎖,然後休眠。
4.當只有乙個執行緒需要被喚醒來處理改變後的狀態時,使用發訊號。如果你為多個謂詞條件使用乙個條件變數,則不能使用發訊號操作:因為你不能分辨是應該喚醒等待這個謂詞條件的執行緒,還是喚醒等待那個謂詞條件的執行緒。不要試圖通過重發訊號繞過去,這可能不會如你所想的傳遞訊號,乙個假喚醒或被攔截喚醒可能導致一系列無意義的重發訊號--20111130更新
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime
注意點:
1.pthread_cond_wait()執行以下原子步驟:
a)釋放mutex
b)阻塞,直到另乙個執行緒觸發了條件變數
c)再加鎖
POSIX執行緒 條件變數
條件變數是 posix 執行緒結構,可以讓您在遇到某些條件時 喚醒 執行緒。可以將它們看作是一種執行緒安全的訊號傳送。如果執行緒正在等待某個特定條件發生,它應該如何處理這種情況?它可以重複對互斥物件鎖定和解鎖,每次都會檢查共享資料結構,以查詢某個值。但這是在浪費時間和資源,而且這種繁忙查詢的效率非常...
posix多執行緒 條件變數
條件變數是用來通知共享資料狀態資訊的。1.條件變數初始化兩種方式 1 靜態初始化 pthread cond t cond pthread cond initializer 示例如下 include typedef struct my struct tag my struct t my struct ...
POSIX條件變數
條件變數 1.當乙個執行緒互斥地訪問某個變數時,他可能發現其他執行緒改變狀態之前,他什麼也不做了 2.例如 乙個執行緒訪問佇列時,發現隊列為空,他只能等待,只到其他執行緒將乙個節點新增到佇列中,這種情況就需要用到條件變數 對於解決無界緩衝區比較好的選擇 函式 pthread cond init初始化...