條件變量概念及為什么需要mutex

轉載于:http://blog.chinaunix.net/uid-27164517-id-3282242.html
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仍然要阻塞。

無論哪種等待方式,都必須和一個互斥鎖配合,以防止多個線程同時請求pthread_cond_wait()(或pthread_cond_timedwait(),下同)的競爭條件(Race Condition)。mutex互斥鎖必須是普通鎖(PTHREAD_MUTEX_TIMED_NP)或者適應鎖 (PTHREAD_MUTEX_ADAPTIVE_NP),且在調用pthread_cond_wait()前必須由本線程加鎖 (pthread_mutex_lock()),而在更新條件等待隊列以前,mutex保持鎖定狀態,并在線程掛起進入等待前解鎖。在條件滿足從而離開 pthread_cond_wait()之前,mutex將被重新加鎖,以與進入pthread_cond_wait()前的加鎖動作對應。

激發條件有兩種形式,pthread_cond_signal()激活一個等待該條件的線程,存在多個等待線程時按入隊順序激活其中一個;而pthread_cond_broadcast()則激活所有等待線程。

下面是另一處說明:給出了函數運行全過程。 為什么在喚醒線程后要重新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
xxxxxxx
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
xxxxxxx
pthread_mutex_unlock
pthread_cond_signal
優點:不會出現之前說的那個潛在的性能損耗,因為在signal之前就已經釋放鎖了
缺點:如果unlock和signal之前,有個低優先級的線程正在mutex上等待的話,那么這個低優先級的線程就會搶占高優先級的線程(cond_wait的線程),而這在上面的放中間的模式下是不會出現的

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容

  • 多線程系列文章源碼頭文件內容: #include #include #include 作為程序員,就是要減少重復勞...
    batbattle閱讀 950評論 0 1
  • 引用自多線程編程指南應用程序里面多個線程的存在引發了多個執行線程安全訪問資源的潛在問題。兩個線程同時修改同一資源有...
    Mitchell閱讀 2,016評論 1 7
  • Q:為什么出現多線程? A:為了實現同時干多件事的需求(并發),同時進行著下載和頁面UI刷新。對于處理器,為每個線...
    幸福相依閱讀 1,605評論 0 2
  • 木窗下的身影 是朦朧的 我唇邊的話語 你聽不到的 幾處燈火闌珊 模糊不清 今生終還是錯過 大漠的風沙 吹盡了過往 ...
    沅芷閱讀 452評論 3 5
  • 60分的媽媽是最完美的。 提問:母子關系不和諧,有時候無法教育他。我從小和爺爺奶奶一起長大,和媽媽關系一直不是很好...
    心理咨詢師于爽閱讀 950評論 0 3