pthread_cond_wait總和乙個互斥鎖結合使用。在呼叫pthread_cond_wait前要先獲取鎖。pthread_cond_wait函式執行時先自動釋放指定的鎖,然後等待條件變數的變化。在函式呼叫返回之前,自動將指定的互斥量重新鎖住。
int pthread_cond_signal(pthread_cond_t * cond);
pthread_cond_signal通過條件變數cond傳送訊息,若多個訊息在等待,它只喚醒乙個。pthread_cond_broadcast可以喚醒所有。呼叫pthread_cond_signal後要立刻釋放互斥鎖,因為pthread_cond_wait的最後一步是要將指定的互斥量重新鎖住,如果pthread_cond_signal之後沒有釋放互斥鎖,pthread_cond_wait仍然要阻塞。
下面是另一處說明:給出了函式執行全過程。 為什麼在喚醒執行緒後要重新mutex加鎖?
了解 pthread_cond_wait() 的作用非常重要 -- 它是 posix 執行緒訊號傳送系統的核心,也是最難以理解的部分。
首先,讓我們考慮以下情況:執行緒為檢視已鏈結列表而鎖定了互斥物件,然而該列表恰巧是空的。這一特定執行緒什麼也幹不了 -- 其設計意圖是從列表中除去節點,但是現在卻沒有節點。因此,它只能:
鎖定互斥物件時,執行緒將呼叫 pthread_cond_wait(&mycond,&mymutex)。pthread_cond_wait() 呼叫相當複雜,因此我們每次只執行它的乙個操作。
pthread_cond_wait() 所做的第一件事就是同時對互斥物件解鎖(於是其它執行緒可以修改已鏈結列表),並等待條件 mycond 發生(這樣當 pthread_cond_wait() 接收到另乙個執行緒的「訊號」時,它將甦醒)。現在互斥物件已被解鎖,其它執行緒可以訪問和修改已鏈結列表,可能還會新增項。 【要求解鎖並阻塞是乙個原子操作】
此時,pthread_cond_wait() 呼叫還未返回。對互斥物件解鎖會立即發生,但等待條件 mycond 通常是乙個阻塞操作,這意味著執行緒將睡眠,在它甦醒之前不會消耗 cpu 週期。這正是我們期待發生的情況。執行緒將一直睡眠,直到特定條件發生,在這期間不會發生任何浪費 cpu 時間的繁忙查詢。從執行緒的角度來看,它只是在等待 pthread_cond_wait() 呼叫返回。
現在繼續說明,假設另乙個執行緒(稱作「2 號執行緒」)鎖定了 mymutex 並對已鏈結列表新增了一項。在對互斥物件解鎖之後,2 號執行緒會立即呼叫函式 pthread_cond_broadcast(&mycond)。此操作之後,2 號執行緒將使所有等待 mycond 條件變數的執行緒立即甦醒。這意味著第乙個執行緒(仍處於 pthread_cond_wait() 呼叫中)現在將甦醒。
現在,看一下第乙個執行緒發生了什麼。您可能會認為在 2 號執行緒呼叫 pthread_cond_broadcast(&mymutex) 之後,1 號執行緒的 pthread_cond_wait() 會立即返回。不是那樣!實際上,pthread_cond_wait() 將執行最後乙個操作:重新鎖定 mymutex。一旦 pthread_cond_wait() 鎖定了互斥物件,那麼它將返回並允許 1 號執行緒繼續執行。那時,它可以馬上檢查列表,檢視它所感興趣的更改。
來看乙個例子(你是否能理解呢?):
in thread1:
pthread_mutex_lock(&m_mutex);
pthread_cond_wait(&m_cond,&m_mutex);
pthread_mutex_unlock(&m_mutex);
in thread2:
pthread_mutex_lock(&m_mutex);
pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex);
為什麼要與pthread_mutex 一起使用呢? 這是為了應對 執行緒1在呼叫pthread_cond_wait()但執行緒1還沒有進入wait cond的狀態的時候,此時執行緒2呼叫了 cond_singal 的情況。 如果不用mutex鎖的話,這個cond_singal就丟失了。加了鎖的情況是,執行緒2必須等到 mutex 被釋放(也就是 pthread_cod_wait() 釋放鎖並進入wait_cond狀態 ,此時執行緒2上鎖) 的時候才能呼叫cond_singal.
pthread_cond_signal即可以放在pthread_mutex_lock和pthread_mutex_unlock之間,也可以放在pthread_mutex_lock和pthread_mutex_unlock之後,但是各有有缺點。
之間:pthread_mutex_lock
******x
pthread_cond_signal
pthread_mutex_unlock
缺點:在某下執行緒的實現中,會造成等待執行緒從核心中喚醒(由於cond_signal)然後又回到核心空間(因為cond_wait返回後會有原子加鎖的 行為),所以一來一回會有效能的問題。但是在linuxthreads或者nptl裡面,就不會有這個問題,因為在linux 執行緒中,有兩個佇列,分別是cond_wait佇列和mutex_lock佇列, cond_signal只是讓執行緒從cond_wait佇列移到mutex_lock佇列,而不用返回到使用者空間,不會有效能的損耗。
所以在linux中推薦使用這種模式。
之後:pthread_mutex_lock
******x
pthread_mutex_unlock
pthread_cond_signal
優點:不會出現之前說的那個潛在的效能損耗,因為在signal之前就已經釋放鎖了
缺點:如果unlock和signal之前,有個低優先順序的執行緒正在mutex上等待的話,那麼這個低優先順序的執行緒就會搶占高優先順序的執行緒(cond_wait的執行緒),而這在上面的放中間的模式下是不會出現的。
再談互斥鎖與條件變數
pthread cond wait總和乙個互斥鎖結合使用。在呼叫pthread cond wait前要先獲取鎖。pthread cond wait函式執行時先自動釋放指定的鎖,然後等待條件變數的變化。在函式呼叫返回之前,自動將指定的互斥量重新鎖住。int pthread cond signal pt...
再談互斥鎖與條件變數
pthread cond wait總和乙個互斥鎖結合使用。在呼叫pthread cond wait前要先獲取鎖。pthread cond wait函式執行時先自動釋放指定的鎖,然後等待條件變數的變化。在函式呼叫返回之前,自動將指定的互斥量重新鎖住。int pthread cond signal pt...
互斥鎖與條件變數
最近複習湯小丹的 計算機作業系統 西安電子科技大學出版社,第三版 程序 執行緒同步章節時,發現乙個疑問。在講程序同步時,提到了兩類方法 訊號量機制和管程機制。訊號量機制又包括四種 整型訊號量 記錄型訊號量 and型訊號量 訊號量集。如果採用整型訊號量或記錄型訊號量,則在共享多個資源時,可能出現程序死...