这种使用增强条件代码有问题吗?

时间:2009-06-23 17:26:34

标签: c++ boost synchronization conditional-statements

此代码是否会等待生产者void push(data)内的互斥锁?

如果是这样,我该如何解决这个问题?

boost::mutex access;
boost::condition cond;

// consumer
data read()
{
  boost::mutex::scoped_lock lock(access);

  // this blocks until the data is ready
  cond.wait(lock);

  // queue is ready
  return data_from_queue();
}

// producer
void push(data)
{
  //<--- will a block ever happen here?
  boost::mutex::scoped_lock lock(access);
  // add data to queue

  cond.notify_one();  
}

假设我有(;;)循环的线程池,我从这个池中的一个线程调用read()。然后我处理它上面的数据。我用一些外部线程调用push()。我的问题是,外部线程是否可以阻止其对push(数据)的调用?

2 个答案:

答案 0 :(得分:8)

wait可以在没有notify被调用的情况下返回。这称为spurious wakeup。要处理这个问题,使用条件的代码应始终在wait周围进行循环,以检查预期条件是否真正有效。例如:

queue data_queue;
boost::mutex access;
boost::condition cond;

// consumer
data read()
{
  boost::mutex::scoped_lock lock(access);

  while (queue.is_empty()) {
    // this blocks until the data is ready
    cond.wait(lock);
  }

  // queue is ready
  return data_from_queue();
}

// producer
void push(data)
{
  boost::mutex::scoped_lock lock(access);

  // add data to queue
  queue.push_back(data);

  cond.notify_one();  
}

从概念上讲,“条件”有点误导。相反,你可以把它想象成一个信号。你正在发出另一个或多个线程的信号,但是你没有任何承诺。只是,“嘿,也许有一些准备好的数据,你为什么不去看看?”

答案 1 :(得分:0)

当调用.wait()时,它将阻塞线程池中的调用线程并释放互斥锁。当有人调用notify_one()或notify_all()时它将返回。在阻塞的线程返回之前,它将重新获取互斥锁并取消阻塞线程池中的线程。

因此,外部线程对void push(data)的调用只会暂时阻塞,直到调用.wait()。

请参阅boost documentation on the condition's wait function