C++ 经典生产者消费者线程
在公园里。当amd在下降时再次唤醒时,C++ 经典生产者消费者线程,c++,multithreading,producer-consumer,C++,Multithreading,Producer Consumer,在公园里。当amd在下降时再次唤醒时,itemCount==BUFFER\u SIZEamd时,生产者睡眠。但一旦itemCount长大,生产者线程就会进入睡眠状态。它如何知道itemCount已下降,需要唤醒?您需要条件变量 条件变量的典型用法如下: //lock the mutex first! scoped_lock myLock(myMutex); //wait till a condition is met myConditionalVariable.wait(myLock, Ch
itemCount==BUFFER\u SIZE
amd时,生产者睡眠。但一旦itemCount
长大,生产者线程就会进入睡眠状态。它如何知道itemCount
已下降,需要唤醒?您需要条件变量
条件变量的典型用法如下:
//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线程,请参见以下内容:
这是一个完整的例子
如果您使用POSIX线程,请参见以下内容:
您可以在这里看到我使用win32原语实现的条件_变量
:
向下滚动,首先查看它的实现,然后查看并发队列实现中的用法。在伪代码中,生产者类似于:
void producer_thread()
{
while(true)
queue.push( produce() );
}
考虑队列推送方法(我在这里使用了pType,但是同样的逻辑适用于其他库)
以及消费者使用的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;
}
它不需要知道——当消费者发出信号时,操作系统会唤醒它。在P-C队列代码中,生产者将对某些OS同步原语进行wait()调用。在使用者线程释放空间并向OS synchro对象发送信号之前,此调用不会返回(除非有故障的OS“支持”虚假唤醒),此时等待的生产者线程将准备就绪,如果有可用的内核,则立即运行-wait()调用将返回
传统上,p-C队列是由一个简单的非线程安全队列、一个保护其索引/指针的互斥体和两个信号量构成的——一个初始化为0以计数队列中的项目,另一个初始化为[queue size]以计数空空间。生产者等待“emptySpace”,当它收到信号时,锁定互斥体,将对象排队,锁定互斥体并发出“itemCount”信号。消费者等待“itemCount”,当它收到信号时,锁定互斥锁,将对象出列,锁定互斥锁并发出“emptySpace”信号。您如何定义条件
?正如纳瓦兹所说,这是条件变量的标准用法。因此,在这段代码中,它将被声明为pthread\u cond\t condition
。不过,我可以用C++11的std::condition\u变量和std::unique\u lock
实现完全相同的逻辑;这是链接的wikipedia页面的“使用监视器”部分中描述的逻辑。
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;
}