2015-07-01 28 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