2014-04-11 77 views
3

我有以下代碼爲count = 0的N個線程運行最初作爲共享變量。在線程工作之前,每個變量都被初始化。我正在嘗試僅執行最大線程數的代碼的關鍵部分。pthread_cond_signal塊線程

void *tmain(){ 
while(1){ 
    pthread_mutex_lock(&count_mutex); 
    count++; 
    if(count>MAX){ 
     pthread_cond_wait(&count_threshold_cv, &count_mutex); 
    } 
    pthread_mutex_unlock(&count_mutex); 
    /* 
    some code not associated with count_mutex or count_threshold_cv 
    */ 
    pthread_mutex_lock(&count_mutex); 
    count--; 
    pthread_cond_signal(&count_threshold_cv); 
    pthread_mutex_unlock(&count_mutex); 
} 
} 

但運行一段時間後,線程在pthread_cond_signal()處被阻塞。我無法理解爲什麼會出現這種情況。任何幫助表示讚賞。

+1

調用'pthread_cond_signal'不會在健康程序中死鎖。您應該驗證您正在操作的條件變量是否仍然存在並且未被損壞。另外,使用調試器來驗證死鎖時不同線程的確切位置,以及它們在那個時刻保持的鎖定位置。 – ComicSansMS

+0

顯示的代碼看起來不錯。如果不起作用,問題就出在其他地方。 Btw:如果將'tmain()'作爲線程函數傳遞給'pthread_create()',則應聲明爲:void * tmain(void *)'。 – alk

+0

我加了[C]標籤。如果你正在做[C++],請糾正這一點。 – alk

回答

3

此代碼有一個弱點,可能會導致阻塞問題。 更確切地說,它不是保護,以防止所謂的虛假喚醒, 也就是說,當沒有信號被調用交付明確的pthread_cond_wait()的函數或者返回調用pthread_cond_signal()或調用pthread_cond_broadcast()。
因此,從下面幾行代碼不保證該線程被喚醒時,計數變量小於或等於MAX

if(count>MAX){ 
    pthread_cond_wait(&count_threshold_cv, &count_mutex); 
} 

讓我們看看當一個線程醒來會發生什麼時計數仍然大於最大值: 之後立即解鎖互斥量。 現在,其他線程可以進入臨界會話,並增加計數變量超過預期:

pthread_mutex_lock(&count_mutex); 
count++; 

如何保護代碼防止雜散信號? pthread_cond_wait喚醒是檢查謂詞(count> MAX)的建議。 如果它仍然是錯誤的,我們需要繼續等待條件變量。 嘗試通過改變如果語句來語句來修復您的代碼(由@alk如說,改變tmain()簽字):

while(count>MAX) 
{ 
    pthread_cond_wait(&count_threshold_cv, &count_mutex); 
} 

現在,如果虛假喚醒發生並且計數仍然大於MAX,那麼流將再次等待條件變量。只有當喚醒伴隨着謂詞變化時,流纔會逃離等待循環。

0

的原因,你的代碼塊是因爲你把計數++等待前:

count++; 
if(count>MAX){ 
     pthread_cond_wait(&count_threshold_cv, &count_mutex); 
} 

相反,你應該寫

while (count >= MAX) { 
     pthread_cond_wait(&count_threshold_cv, &count_mutex); 
} 
count++; 

的原因是,數應工作線程的數量。 線程只能在完成等待時遞增計數。

另一方面,您的count變量計算工作線程的數量加上等待線程的數量。這個計數太大,導致條件計數> MAX是正確的哪些塊。

你應該用MichaelGoren寫的「while」替換「if」。使用「if」而不是「while」不會導致阻塞,而是會導致太多的線程同時運行;即使count> MAX,喚醒線程也開始工作。

您需要「while」的原因是pthread_cond_signal解鎖了其中一個等待線程。然而,未阻塞的線程仍在等待互斥體,並且它不一定計劃運行。當喚醒線程最終獲得互斥並開始運行時,對pthread_cond_wait的調用返回。同時,在pthread_cond_signal和pthread_cond_wait的返回之間,其他線程可能擁有該互斥體。所以你必須再次檢查這種情況,這是「一會兒」所做的。

另外,因爲count ++現在在等待之後,條件變爲count> = MAX而不是count> MAX。即使工人數量爲MAX,您也應該等待。

或者,您可以使用這個問題的信號量。