提升条件变量 - 调用“notify_one”堆栈?

时间:2013-01-29 12:07:03

标签: c++ boost boost-thread

在使用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()唤醒(因为它仍在忙着做其他工作),并且想知道是否缺乏“堆叠”可能是原因。

如果(有时)消费者线程无法跟上生产者线程,似乎没有堆叠此代码将失败。如果我的理论是正确的,我会很感激如何纠正这个代码的建议。

2 个答案:

答案 0 :(得分:7)

notify_one的规范是:

  

C ++ 11 30.5.1 / 7:效果:如果有任何线程被阻塞等待*this,则取消阻止其中一个theads。

所以答案是否定的:对notify_onenotify_all的调用只会唤醒当前正在等待的线程,并且不会被记住以供日后使用。

更新:抱歉,我误解了std::condition_variable这个问题。毫不奇怪,Boost规范或多或少相同:

  

如果在*thiswait的通话中timed_wait上有任何线程阻止,则取消阻止其中一个主题。

关于你的编辑:如果有人在调用push时没有线程等待,那么下一个要调用pop的线程将不会等待,因为the_queue不会为空。因此,条件变量不需要记住它不应该等待;该信息存储在被管理的状态,而不是条件变量。如果消费者无法跟上生产者的步伐,那么您需要加快消费或减缓生产;你无法对信号机制做任何帮助。

答案 1 :(得分:3)

简而言之:不,它不会叠加。

notify_one()仅在另一个线程在cond_var上等待时生效。因此,如果您的消费者在等待,则第一个notify_one()已取消阻止消费者。第二个notify_one()没有效果,因为没有线程在等待condition_variable