Есть ли проблема с этим использованием кода условия повышения? - PullRequest
1 голос
/ 23 июня 2009

Будет ли этот код ждать мьютекс внутри 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();  
}

Допустим, у меня есть пул потоков для цикла (;;), и я прочитал (), вызываемый из потока в этом пуле. Затем я обрабатываю данные на нем. И я вызываю push () с каким-то внешним потоком. У меня такой вопрос, может ли этот внешний поток когда-либо блокировать вызов push (data)?

Ответы [ 2 ]

8 голосов
/ 23 июня 2009

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

Концептуально «состояние» является своего рода заблуждением. Вместо этого вы можете думать об этом как о сигнале. Вы даете сигнал другому потоку или потокам проснуться, но ничего не обещаете. Просто, «Эй, может быть, есть некоторые данные готовы, почему бы тебе не проверить, а?»

0 голосов
/ 23 июня 2009

Когда вызывается .wait (), он блокирует вызывающий поток в вашем пуле потоков и освобождает мьютекс. Он вернется, когда кто-то вызовет notify_one () или notify_all (). Перед тем как поток, который был заблокирован, вернется, он повторно получит мьютекс и разблокирует поток в вашем пуле потоков.

Таким образом, вызов void push(data) вашим внешним потоком будет временно блокироваться до тех пор, пока не будет вызван .wait ().

См. Документацию boost для функции ожидания условия .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...