1

这段代码会在生产者内部的互斥体上等待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();  
}

假设我有一个 for(;;) 循环的线程池,并且我已经从该池中的线程调用了 read()。然后我处理它的数据。我用一些外部线程调用 push() 。我的问题是,该外部线程能否阻止其对 push(data) 的调用?

4

2 回答 2

8

wait可以在不notify被调用的情况下返回。这称为虚假唤醒。为了处理这个问题,使用条件的代码应该总是有一个循环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();  
}

从概念上讲,“条件”有点误导。相反,您可以将其视为一个信号。您正在向另一个或多个线程发出信号以唤醒,但您并没有承诺任何事情。只是,“嘿,也许有一些数据准备好了,你为什么不去检查一下?”

于 2009-06-23T17:36:09.913 回答
0

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

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

请参阅有关条件的等待功能的 boost 文档

于 2009-06-23T18:11:19.613 回答