2015-07-01 32 views
0

我正在運行下面的代碼塊。這段代碼將創建5個從線程和1個主線程。所有從屬線程都等待主線程準備好數據,當數據準備就緒時,所有從屬線程都會通知開始處理。如何確保所有從屬線程都等待條件變量?

我的問題是,有可能在從屬線程開始等待conditional_variable之前,主線程將數據準備好並通知等待的線程。在這種情況下,一些被等待的線程會得到通知並開始處理,但是沒有被等待的線程將開始等待一個永遠不會到來的通知。

如果你運行這個例子,這種情況不會發生,但我正在尋找一種方法來確保所有從屬線程正在等待通知,然後通知他們。你知道我該怎麼做?

/* 
    Condition Variables - Many waiting threads 

    Shows how one condition variable can be used to notify multiple threads 
    that a condition has occured. 

    * Part of "Threading with Boost - Part IV: Condition Variables", published at: 

     http://antonym.org/boost 

    Copyright (c) 2015 Gavin Baker <[email protected]> 
    Published under the MIT license, see LICENSE for details 
*/ 

#include <cstdio> 

#include <boost/thread.hpp> 

boost::condition_variable data_ready_cond; 
boost::mutex data_ready_mutex; 
bool data_ready = false; 

void master_thread() 
{ 
    printf("+++ master thread\n"); 

    // Pretend to work 
    printf(" master sleeping...\n"); 
    boost::chrono::milliseconds sleepDuration(750); 
    boost::this_thread::sleep_for(sleepDuration); 

    // Let other threads know we're done 
    printf(" master notifying...\n"); 
    data_ready = true; 
    data_ready_cond.notify_all(); 

    printf("--- master thread\n"); 
} 

void slave_thread(int id) 
{ 
    printf("+++ slave thread: %d\n", id); 

    boost::unique_lock<boost::mutex> lock(data_ready_mutex); 
    while (!data_ready) 
    { 
     data_ready_cond.wait(lock); 
    } 

    printf("--- slave thread: %d\n", id); 
} 

int main() 
{ 
    printf("Spawning threads...\n"); 

    boost::thread slave_1(slave_thread, 1); 
    boost::thread slave_2(slave_thread, 2); 
    boost::thread slave_3(slave_thread, 3); 
    boost::thread slave_4(slave_thread, 4); 

    boost::thread master(master_thread); 

    printf("Waiting for threads to complete...\n"); 

    slave_1.join(); 
    slave_2.join(); 
    slave_3.join(); 
    slave_4.join(); 
    master.join(); 

    printf("Done\n"); 

    return 0; 
} 
+0

當調試代碼將某些代碼隨機睡眠在線程內時,大多數時候我都會通過這種方式捕獲一些錯誤。你想要一些線程沒有看到通知,然後在它發生之前讓它進入休眠狀態,並且看到它有一些條件forcin其他人等待它 – GameDeveloper

+2

你的條件謂詞是'data_ready',而你正在'master_thread'中修改它,而沒有互斥量,唯一目的是保護它,*閂鎖*。這本身就是錯誤的。 – WhozCraig

+0

@WhozCraig這應該是答案 – Slava

回答

3

你有競爭條件 - 設置標誌和通知從屬線程不是原子的。因此,在修改主線程中的data_ready標誌之前,您只需鎖定data_ready_mutex即可。這將消除競態條件,從線程或者將看到data_ready爲假並且等待條件變量並且將被通知,或者僅在data_ready被設置爲true並且因此它不會等待時纔會獲得互斥鎖。

+0

這是儘可能準確,我可以/會寫它。 cvars + mutexes的基本規則很簡單:*除非謂詞互斥鎖被鎖定,否則不要更改,甚至不檢查謂詞數據狀態。*主線程違反了基本規則。 Upticked。 – WhozCraig