在使用Boost线程的单个生产者/单个使用者应用程序中,如果生产者线程在使用者线程调用cond_var.notify_one()
之前对cond_var.wait(lock)
进行多次调用会发生什么?
是否会对notify_one
的其他来电进行叠加,以便每次拨打.wait()
的电话都会与.notify_one()
电话1:1对应?
编辑用于实现并发队列的commonly quoted example具有以下方法:
void push(Data const& data)
{
boost::mutex::scoped_lock lock(the_mutex);
the_queue.push(data);
lock.unlock();
the_condition_variable.notify_one();
}
void wait_and_pop(Data& popped_value)
{
boost::mutex::scoped_lock lock(the_mutex);
while(the_queue.empty())
{
the_condition_variable.wait(lock);
}
popped_value=the_queue.front();
the_queue.pop();
}
我使用了一些非常相似的代码,并且经历了一些奇怪的内存增长,这似乎可以解释为消费者线程没有为每个.notify_one()
唤醒(因为它仍在忙着做其他工作),并且想知道是否缺乏“堆叠”可能是原因。
如果(有时)消费者线程无法跟上生产者线程,似乎没有堆叠此代码将失败。如果我的理论是正确的,我会很感激如何纠正这个代码的建议。
答案 0 :(得分:7)
notify_one
的规范是:
C ++ 11 30.5.1 / 7:效果:如果有任何线程被阻塞等待
*this
,则取消阻止其中一个theads。
所以答案是否定的:对notify_one
和notify_all
的调用只会唤醒当前正在等待的线程,并且不会被记住以供日后使用。
更新:抱歉,我误解了std::condition_variable
这个问题。毫不奇怪,Boost规范或多或少相同:
如果在
*this
或wait
的通话中timed_wait
上有任何线程阻止,则取消阻止其中一个主题。
关于你的编辑:如果有人在调用push
时没有线程等待,那么下一个要调用pop
的线程将不会等待,因为the_queue
不会为空。因此,条件变量不需要记住它不应该等待;该信息存储在被管理的状态,而不是条件变量。如果消费者无法跟上生产者的步伐,那么您需要加快消费或减缓生产;你无法对信号机制做任何帮助。
答案 1 :(得分:3)
简而言之:不,它不会叠加。
notify_one()
仅在另一个线程在cond_var
上等待时生效。因此,如果您的消费者在等待,则第一个notify_one()
已取消阻止消费者。第二个notify_one()
没有效果,因为没有线程在等待condition_variable