boost :: condition_variable :: notify_one()上的并发

时间:2012-10-15 13:30:28

标签: c++ boost synchronization race-condition condition-variable

我有一个异步处理任务的“引擎”,我希望等待一项任务,直到处理完该任务。

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

但并发性仍然存在......我该如何解决这个问题?

1 个答案:

答案 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(),或虚假通知线程将取消阻止。