2013-06-03 48 views
22

我正在使用条件变量来停止线程,直到另一个线程完成处理它的任务队列(长篇故事)。因此,在一个线程我锁和等待:如何使用boost条件变量来等待线程完成处理?

boost::mutex::scoped_lock lock(m_mutex); 
m_condition.wait(lock); 

一旦其它线程已经完成它的任务,它标志着等待线程如下:

boost::mutex::scoped_lock lock(m_parent.m_mutex); 
m_parent.m_condition.notify_one(); 

我看到的问题是等待线程不会停止等待,除非我在它后面的指令上设置断点(我正在使用xcode,fyi)。是的,这看起来很奇怪。有谁知道为什么会发生这种情况?我错用了条件变量吗?

+0

的代码是一个有点混乱......是第一个'm_mutex'相同的实例作为第二个'm_parent.m_mutex'? –

回答

42

是的,你滥用条件变量。 “条件变量”实际上只是信号机制。你还需要测试一个条件。在你的情况下,可能发生的事情是,调用notify_one()的线程实际上在调用wait()的线程开始之前完成。 (或者至少,notify_one()呼叫在wait()呼叫之前发生。)这被称为“错过唤醒”。

的解决方案是真正有一个包含你所关心的条件变量:

bool worker_is_done=false; 

boost::mutex::scoped_lock lock(m_mutex); 
while (!worker_is_done) m_condition.wait(lock); 

boost::mutex::scoped_lock lock(m_mutex); 
worker_is_done = true; 
m_condition.notify_one(); 

如果worker_is_done==true其他线程甚至开始然后就等着之前你只下跌直接通过while循环而无需调用wait()

这种模式很常见,我甚至可以说如果你没有while循环包装你的condition_variable.wait(),那么你总是有一个错误。事实上,当C++ 11采用了类似于升压的东西::接受一个谓词lambda表达式condtion_variable他们增加了一种新的等待(的)(基本上它的while循环你):

std::condition_variable cv; 
std::mutex m; 
bool worker_is_done=false; 


std::unique_lock<std::mutex> lk(m); 
cv.wait(lk, []{return worker_is_done;}); 
+0

什么是'boost :: mutex :: scoped_lock lock(m_mutex);'在需要等待的线程中? notify_one()不需要参数。 – ItsmeJulian

+0

它提供了一个原子写入'worker_is_done'。另一种方法是将类型声明为“原子”而不是“bool”。 –

+0

@DavidStone如果我们在一个处理器上运行代码,其中1字节的赋值是基本的,例如。 86?在这种情况下我们不需要锁,是吗? – user3286661

2

我已经实施了一个例子,说明如何使用提升条件,在讨论中。

#include <iostream> 

#include <boost/asio.hpp> 
#include <boost/thread/mutex.hpp> 
#include <boost/thread/thread.hpp> 

boost::mutex io_mutex; 
bool worker_is_done = false; 
boost::condition_variable condition; 

void workFunction() 
{ 
    std::cout << "Waiting a little..." << std::endl; 
    boost::this_thread::sleep(boost::posix_time::seconds(1)); 
    worker_is_done = true; 
    std::cout << "Notifying condition..." << std::endl; 
    condition.notify_one(); 
    std::cout << "Waiting a little more..." << std::endl; 
    boost::this_thread::sleep(boost::posix_time::seconds(1)); 
} 

int main() 
{ 
    boost::mutex::scoped_lock lock(io_mutex); 
    boost::thread workThread(&workFunction); 

    while (!worker_is_done) condition.wait(lock); 
    std::cout << "Condition notified." << std::endl; 
    workThread.join(); 
    std::cout << "Thread finished." << std::endl; 

    return 0; 
} 

Boost condition variable example

+3

在将worker_is_done设置为true之前,您不应该在workFunction中使用锁吗? –

+0

我认为他应该。 –