经典生产者消费者线程

时间:2012-06-24 18:32:50

标签: c++ multithreading producer-consumer

Classical producer consumer problem中。生产者在itemCount == BUFFER_SIZE amd再次醒来时会睡觉。但是一旦itemCount成长,生产者线程就会陷入困境。怎么知道itemCount已经失效,需要wakeup

3 个答案:

答案 0 :(得分:2)

在伪代码中,生产者是这样的:

void producer_thread()
{
    while(true)
        queue.push( produce() );
}

所以考虑一下队列推送方法(我在这里使用过pthreads,但同样的逻辑适用于其他库)

void SynchronizedQueue::push(Item const &i)
{
    pthread_mutex_lock(&mutex);

    // queue is full, so wait for consumer
    while (queue.size() == BUFFER_SIZE)
        pthread_cond_wait(&condition, &mutex);

    // when we get here, the queue has space
    this->queue.push_back(i);

    // make sure we wake a sleeping consumer
    if (queue.size() == 1)
        pthread_cond_signal(&condition);

    pthread_mutex_unlock(&mutex);
}

和消费者使用的pop方法:

Item SynchronizedQueue::pop()
{
    pthread_mutex_lock(&mutex);

    // wait for something to do
    while (queue.size() == 0)
        pthread_cond_wait(&condition, &mutex);

    // if we get here, we have some work
    Item tmp = queue.front();

    // make sure we wake a sleeping producer
    if (queue.size() == BUFFER_SIZE)
        pthread_cond_signal(&condition)

    queue.pop_front();
    pthread_mutex_unlock(&mutex);
    return tmp;
}

答案 1 :(得分:1)

您需要条件变量。

条件变量的典型用法是:

//lock the mutex first!
scoped_lock myLock(myMutex); 

//wait till a condition is met
myConditionalVariable.wait(myLock, CheckCondition);

//Execute this code only if the condition is met

其中CheckCondition是一个检查条件的函数(或函子)(例如,关于何时唤醒)。它在虚假唤醒时由内部wait()函数调用,如果条件尚未满足,则wait()函数再次休眠。在进入睡眠状态之前,wait()会释放互斥锁,原子地


如果你的编译器支持C ++ 11引入的std::conditional,那么你可以看到这个细节:

如果您的编译器不支持它,并且您使用的是win32线程,请参阅:

here就是一个完整的例子。

如果您使用POSIX线程,请参阅:


您可以在此处使用win32原语查看我的conditional_variable实现:

向下滚动并首先查看它的实现,然后查看并发队列实现中的用法。

答案 2 :(得分:0)

它不需要知道 - 当消费者发出信号时,操作系统会将其唤醒。在P-C队列代码中,生产者将对某个OS同步原语进行wait()调用。在消费者线程发出空间并向OS同步对象发出信号之前,此调用不会返回(除非您的错误操作系统'支持'虚假唤醒),此时等待的生产者线程将准备就绪,如果有可用的核心,立即运行 - wait()调用将返回。

传统上,PC队列是由一个简单的非线程安全队列,一个保护其索引/指针的互斥锁和两个信号量构成的 - 一个初始化为0以计算队列中的项目,一个初始化为[队列大小]算空的空间。生产者等待'emptySpace',当它获得信号时,锁定互斥锁,将对象排入队列,锁定互斥锁并发出'itemCount'信号。消费者等待'itemCount',当它收到信号时,锁定互斥锁,使对象出列,锁定互斥锁并发出'emptySpace'信号。