我有一个异步处理任务的“引擎”,我希望等待一项任务,直到处理完该任务。
boost::condition_variable cvWorkDone;
DoSomeWork()
{
PostAsyncJob(DoWorkAsync) // is a boost::asio::post
boost::mutex::scoped_lock lock(mtxWorkDoneCv);
cvWorkDone.wait(lock);
}
DoWorkAsync()
{
// do some work ...
cvWorkDone.notify_one();
}
问题是上面的代码有竞争条件。如果DoWorkAsync()
在boost::condition_variable
等待之前通知DoSomeWork()
该怎么办?
我看到boost::condition_variable::wait
有第二个参数,bool可以用来实现这样的东西
bool bWait;
DoSomeWork()
{
bWait = true;
PostAsyncJob(DoWorkAsync) // boost::asio::post
boost::mutex::scoped_lock lock(mtxWorkDoneCv);
cvWorkDone.wait(lock, bWait);
}
DoWorkAsync()
{
// do some work ...
boost::mutex::scoped_lock lock(mtxWorkDoneCv);
cvWorkDone.notify_one();
bWait = false;
}
但并发性仍然存在......我该如何解决这个问题?
答案 0 :(得分:3)
由于条件变量不保持关于它们是否已被发信号通知的状态,因此您需要维持状态,以便条件变量单独发出信号(在某些情况下,例如队列,条件变量发出信号的原因可以异步消失。所以你的代码可能会有这样的东西:
boost::condition_variable cvWorkDone;
bool workdone = false;
DoSomeWork()
{
PostAsyncJob(DoWorkAsync) // is a boost::asio::post
boost::mutex::scoped_lock lock(mtxWorkDoneCv);
while (!workdone) {
cvWorkDone.wait(lock);
}
}
DoWorkAsync()
{
// do some work ...
{
boost::mutex::scoped_lock lock(mtxWorkDoneCv);
workdone = true;
}
cvWorkDone.notify_one();
}
请注意,这也可以防止来自boost::condition_variable::wait()
的虚假回报。来自boost::condition_variable::wait()
上的提升文档:
通过调用this-> notify_one()或this-> notify_all(),或虚假通知线程将取消阻止。