2011-04-07 36 views
2

在我的計劃喚醒有有等待從其它代碼的一部分喚醒部分代碼:
下面是進入睡眠狀態的一部分:調用pthread_cond_wait不調用pthread_cond_broadcast

void flush2device(int task_id) { 

if (pthread_mutex_lock(&id2cvLock) != SUCCESS) { 
    cerr << "system error - exiting!!!\n"; 
    exit(1); 
} 

map<int,pthread_cond_t*>::iterator it; 

it = id2cv.find(task_id); 

if(it == id2cv.end()){ 

    if (pthread_mutex_unlock(&id2cvLock) != SUCCESS) { 
     cerr << "system error\n UNLOCKING MUTEX flush2device\n"; 
     exit(1); 
    } 

    return; 
} 

cout << "Waiting for CV signal" <<endl; 

if(pthread_cond_wait(it->second, &id2cvLock)!=SUCCESS){ 
    cerr << "system error\n COND_WAIT flush2device - exiting!!!\n"; 
    exit(1); 
} 
cout << "should be right after " << task_id << " signal" << endl; 


if (pthread_mutex_unlock(&id2cvLock) != SUCCESS) { 
    cerr << "system error\n UNLOCKING MUTEX flush2device -exiting!!!\n"; 
    exit(1); 
} 

}
在代碼的另一部分,有(信令)的醒來部分:

//id2cv is a map <int, pthread_cond_t*> variable. - the value is a pointer to the cv on 
//which we call with the broadcast method. 
if(pthread_mutex_lock(&id2cvLock)!=SUCCESS){ 
    cerr <<"system error\n"; 
    exit(1); 
} 

id2cv.erase(nextBuf->_taskID); 

cout << "In Thread b4 signal, i'm tID " <<nextBuf->_taskID << endl; 
    if (pthread_cond_broadcast(nextBuf->cv) != 0) { 
     cerr << "system error SIGNAL_CV doThreads\n"; 
     exit(1); 
    } 
cout << "In doThread, after erasing id2cv " << endl; 
if(pthread_mutex_unlock(&id2cvLock)!=SUCCESS){ 
    cerr <<"system error\n; 
    exit(1); 
} 

大多數奔跑的工作得很好,但過一段時間的程序只是停止「反應」 - 第一種方法(ABO ve)只是沒有通過cond_wait部分 - 似乎沒有人真的按時(或從其他原因)向她發送信號 - 而另一種方法(最後一部分代碼是它的一部分)繼續運行。

我在哪裏出錯了互斥和信號的邏輯?在調用cond_wait和cond_broadcast方法之前,我已經檢查過pthread_cond_t變量仍然「活着」,並且該區域中沒有任何內容似乎是錯誤的。

回答

0

我不認爲在「喚醒」部分中有足夠的代碼,但我最初的猜測是pthread_cond_waitpthread_cond_broadcast發佈時尚未輸入。

另一種可能性是pthread_cond_wait處於虛假喚醒的中間並完全沒有信號。

我敢肯定,條件變量的大多數用法也有一個外部謂詞,每次喚醒後都必須檢查它,看看是否有工作要做。

+0

感謝您的快速回復。重新調整fisrt建議 - 我使用與喚醒部分必須獲得的相同鎖來鎖定等待部分才能調用廣播 - 這樣,如果調用廣播 - 第一個必須等​​待(放棄互斥鎖)。變量本身肯定仍然有效 - 在兩次調用之間沒有人觸及它。 – Zach 2011-04-07 14:25:42

2

您使用pthread_cond_wait()是不正確的。如果一個條件變量在沒有進程正在等待時發出信號,則該信號不起作用。它不會在下一次進程等待時保存。這意味着,正確使用pthread_cond_wait()樣子:

pthread_mutex_lock(&mutex); 
/* ... */ 
while (!should_wake_up) 
    pthread_cond_wait(&cond, &mutex); 

should_wake_up條件可能只是一個標誌變量的一個簡單的測試,也可能是這樣的一個更復雜的測試緩衝區爲空或滿,或相似的東西。必須鎖定互斥鎖,以防止可能會改變should_wake_up結果的併發修改。

不清楚你的程序應該做什麼測試 - 你可能需要添加一個特定的標誌變量。

5

儘管它的名稱,pthread_cond_waitun有條件的等待條件。除非您確認有需要等待的東西,並且它正在等待的東西必須由關聯的互斥鎖保護,否則您不能撥打pthread_cond_wait

條件變量是無狀態的,應用程序有責任存儲被等待的東西的狀態,稱爲「謂詞」。

的典型模式是:

pthread_mutex_lock(&mutex); 
while(!ready_for_me_to_do_something) 
    pthread_cond_wait(&condvar, &mutex); 
do_stuff(); 
ready_for_me_to_do_something=false; // this may or may not be appropriate  
pthread_mutex_unlock(&mutex); 

和:

pthread_mutex_lock(&mutex); 
ready_for_me_to_do_something=true; 
pthread_cond_broadcast(&condvar); 
pthread_mutex_unlock(&mutex); 

注意這個代碼是如何保持在一個循環中ready_for_me_to_do_something變量和等待線程等待狀態,直到該變量是真實的。注意互斥體如何保護該共享變量,並保護條件變量(因爲這也是線程間共享的)。

這不是使用條件變量的唯一正確方法,但它很容易遇到任何其他用途的麻煩。即使沒有理由等待,您也可撥打pthread_cond_wait。如果您在使用前等待姐姐帶着車回家,而她已經回來了,您會等很久。

相關問題