如何使用boost条件变量来等待线程完成处理

How do I use a boost condition variable to wait for a thread to complete processing?

本文关键字:线程 处理 等待 何使用 boost 条件 变量      更新时间:2023-10-16

我使用一个条件变量来停止一个线程,直到另一个线程完成处理它的任务队列(长话短说)。因此,在一个线程上,我锁定并等待:

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,供参考)。是的,这看起来很奇怪。有人知道为什么会这样吗?我是否误用了条件变量?

是的,您错误地使用了条件变量。"条件变量"实际上只是信号机制。你还需要测试一种情况。在您的例子中,可能发生的情况是,调用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,那么你就会在没有调用wait()的情况下直接陷入while循环。

这个模式是如此普遍,以至于我几乎可以说,如果你没有一个while循环包装你的condition_variable.wait(),那么你总是有一个错误。事实上,当c++ 11采用类似boost:: condition_variable的东西时,它们添加了一种新的wait()方法,它接受谓词lambda表达式(本质上是为您执行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;});

在讨论的基础上,我已经实现了一个示例来说明如何使用boost条件。

#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;
}

升压条件变量示例