Есть проблема с этим использованием кода условия повышения
-
06-07-2019 - |
Вопрос
Будет ли этот код ждать мьютекс внутри 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 (data)?
Решение
Когда вызывается .wait (), он блокирует вызывающий поток в вашем пуле потоков и освобождает мьютекс. Он вернется, когда кто-то вызовет notify_one () или notify_all (). Перед тем как поток, который был заблокирован, вернется, он повторно получит мьютекс и разблокирует поток в вашем пуле потоков. Р>
Таким образом, вызов void push (data)
вашим внешним потоком будет временно блокироваться до тех пор, пока не будет вызван .wait (). Р>
См. расширенную документацию по функции ожидания условия. . р>
Другие советы
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();
}
Концептуально, «условие» это своего рода заблуждение. Вместо этого вы можете думать об этом как о сигнале. Вы даете сигнал другому потоку или потокам проснуться, но ничего не обещаете. Просто "Эй, может быть, есть некоторые данные готовы, почему бы вам не проверить, а?"