2009-07-16 67 views
44

我正在學習pthread和等待條件。至於我可以告訴一個典型的等待線程是這樣的:Pthread和等待條件

pthread_mutex_lock(&m); 
while(!condition) 
    pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

我不能理解的是,爲什麼線while(!condition)非常必要,即使我用pthread_cond_signal()來喚醒線程。

我可以理解,如果我用pthread_cond_broadcast()我需要測試的條件,因爲我醒來所有等待線程,其中一個可以解鎖互斥(因此轉移執行到另一個喚醒之前再次使病情假線程不應該在這一點執行)。 但是,如果我使用pthread_cond_signal()我醒來只是一個線程所以條件必須是真實的。所以代碼可能是這樣的:

pthread_mutex_lock(&m); 
pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

我讀了一些關於可能發生的虛假信號。這(並且僅此)是原因嗎?爲什麼我應該有虛假singnals?或者還有別的東西我沒有得到?

我假設的信號代碼是這樣的:

pthread_mutex_lock(&m); 
condition = true; 
pthread_cond_signal(&cond); // Should wake up *one* thread 
pthread_mutex_unlock(&m); 

回答

43

您應該將pthread_cond_wait放在while循環中的真正原因不是因爲虛假喚醒。即使您的條件變量沒有虛假喚醒,您仍然需要循環來捕獲常見類型的錯誤。爲什麼?考慮如果多個線程等待在相同條件下可能發生的事情:

Thread 1       Thread 2   Thread 3 
check condition (fails) 
(in cond_wait) unlock mutex 
(in cond_wait) wait 
           lock mutex 
           set condition 
           signal condvar 
           unlock mutex 
                lock mutex 
                check condition (succeeds) 
                do stuff 
                unset condition 
                unlock mutex 
(in cond_wait) wake up 
(in cond_wait) lock mutex 
<thread is awake, but condition 
is unset> 

的這裏的問題是,線程必須等待之前釋放互斥體,可能允許另一個線程來「竊取」無論該線程在等待。除非保證只有一個線程可以等待該條件,否則在線程喚醒時假定條件有效是不正確的。

15

假設你不檢查的條件。那麼通常你無法避免以下壞事發生了(至少,你無法避免它的一行代碼):

Sender        Receiver 
locks mutex 
sets condition 
signals condvar, but nothing 
    is waiting so has no effect 
releases mutex 
            locks mutex 
            waits. Forever. 

當然你的第二個代碼示例可避免此做:

pthread_mutex_lock(&m); 
if (!condition) pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

那麼肯定會出現這樣的情況,如果只有最多一個接收者,並且如果cond_signal是唯一能夠喚醒它的東西,那麼它只會在條件設置時醒來,因此不需要循環。 nos涵蓋了爲什麼第二個「如果」不是真的。

+0

我明白了,所以由於邏輯原因(無盡的等待)需要「if」,但由於實現問題(虛假信號),實際需要一段時間。 – Emiliano 2009-07-16 11:40:24

+0

是的,當我第一次使用pthreads庫時,我問了同樣的問題。我省略了檢查狀態變量,並且在等待發生之前我的程序會發出信號。這是等待/信號功能的全部要點。等待併發出一些互斥保護的內存狀態變化信號。 – 2011-03-25 15:09:46