1

我有一个异步处理任务的“引擎”,对于一个任务,我想等到该任务处理完毕。

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

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

4

1 回答 1

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 文档boost::condition_variable::wait()

当调用 this->notify_one() 或 this->notify_all()或 spuriously时,线程将解除阻塞。

于 2012-10-15T14:38:54.260 回答