天天看點

深入了解 pthread_cond_wait()

在多線程同步互斥的應用場景下,通常會用到pthread_cond_wait()和pthread_cond_signal()函數。那麼這兩個函數到底是如何保證互斥同步的呢?

為了對上面的問題有個直覺的了解,可以從下面的問題着手。下面兩段這些程式有什麼bug麼?

a. 等待條件的線程執行的代碼:

Thread 1:

{

……………………..

pthread_cond_wait(cv, mutex);

do_worker_task();

}

b.喚醒等待線程的代碼:

pthread_mutex_lock(mutx);

pthread_cond_signal(cv)

pthread_mutex_unlock(mutex);

要知道上面代碼問題在哪,關鍵是必須對pthread_cond_wait()有深入的了解。為了對這個函數又直覺的了解,下面給出了pthread_cond_wait(cv, mutex)正常執行過程中的幾個重要子步驟僞碼:

pthread_cond_wait(cv, mutex) 實際做的事情:

a. pthread_mutex_unlock(mutex);

b. do_real_cond_wait(cv); // 可能在這阻塞直到其他線程調用pthread_cond_signal(cv)或者  pthread_cond_broadcast(cv),才會往下執行

c. pthread_mutex_lock(mutex);

結合在多處理器、多線程、高并發的環境下,上面三個步驟就顯得缺一不可,才能保證盡可能地互斥:

步驟a:保證其他線程此後也有等待、申請條件變量的同等機會

步驟b:在條件變量還沒就緒的情況下,執行真正的阻塞

步驟c:目前線程得到條件變量之後,阻止其他等待條件變量的線程繼續往下執行,而自己可以往下執行。

那麼問題來了,考慮步驟c,如果單獨一句pthread_cond_wait(cv, mutex)是無法確定線程盡可能互斥的,這就是為何在執行pthread_cond_wait()之前要求有pthread_mutex_lock(mutx)的原因了,是以正常申請條件變量的線程的流程應該如下:

至于釋放條件變量,了解了上邊的内部機制之後,其實在釋放條件變量之前就不需要申請鎖再釋放鎖了。

這裡要特别提到的一點是,按照上面正确申請條件變量的的流程,仍然存在多個等待條件變量的線程同時執行步驟b出等待,此時如果有信号釋放,就會喚醒多個線程。這也就是為什麼手冊上說pthread_cond_signal(cv)至少喚醒一個在等待cv的線程(可以計數資源為1)的原因了。

參考文檔和手冊:

man pthread_cond_signal

本文轉自存儲之廚51CTO部落格,原文連結:http://blog.51cto.com/xiamachao/1952614 ,如需轉載請自行聯系原作者

繼續閱讀