我在拙作《Linux 多線程服務端程式設計:使用 muduo C++ 網絡庫》第 2.2 節總結了條件變量的使用要點:
條件變量隻有一種正确使用的方式,幾乎不可能用錯。對于 wait 端:
1. 必須與 mutex 一起使用,該布爾表達式的讀寫需受此 mutex 保護。
2. 在 mutex 已上鎖的時候才能調用 wait()。
3. 把判斷布爾條件和 wait() 放到 while 循環中。
對于 signal/broadcast 端:
1. 不一定要在 mutex 已上鎖的情況下調用 signal (理論上)。
2. 在 signal 之前一般要修改布爾表達式。
3. 修改布爾表達式通常要用 mutex 保護(至少用作 full memory barrier)。
4. 注意區分 signal 與 broadcast:“broadcast 通常用于表明狀态變化,signal 通常用于表示資源可用。(broadcast should generally be used to indicate state change rather than resource availability。)”
版本一:錯誤。某書上的原始版,有丢失事件的可能。

版本二:錯誤。lock() 之後再 signal(),同樣有丢失事件的可能。
版本三:錯誤。引入了 bool signaled_; 條件,但沒有正确處理 spurious wakeup。
版本四五六:正确。僅限 single waiter 使用。
版本七:最佳。可供 multiple waiters 使用。
總結:使用條件變量,調用 signal() 的時候無法知道是否已經有線程等待在 wait() 上。是以一般總是要先修改“條件”,使其為 true,再調用 signal();這樣 wait 線程先檢查“條件”,隻有當條件不成立時才去 wait(),避免了丢事件的可能。換言之,通過使用“條件”,将邊沿觸發(edge trigger)改為電平觸發(level trigger)。這裡“修改條件”和“檢查條件”都必須在 mutex 保護下進行,而且這個 mutex 必須用于配合 wait()。
思考題:如果用兩個 mutex,一個用于保護“條件”,另一個專門用于和 cond 配合 wait(),會出現什麼情況?
本文轉自 陳碩 部落格園部落格,原文連結:http://www.cnblogs.com/Solstice/p/3309089.html,如需轉載請自行聯系原作者