我正在阅读pthread.h
;与条件变量相关的函数(如pthread_cond_wait(3)
)需要一个互斥锁作为参数.为什么?据我所知,我将创建一个互斥锁just作为该参数?那个互斥体应该做什么?
我正在阅读pthread.h
;与条件变量相关的函数(如pthread_cond_wait(3)
)需要一个互斥锁作为参数.为什么?据我所知,我将创建一个互斥锁just作为该参数?那个互斥体应该做什么?
这只是条件变量实现(或最初实现)的方式.
互斥锁用于保护the condition variable itself.这就是为什么你需要在等待前把它锁上.
等待将"自动"解锁互斥锁,允许其他人访问条件变量(用于发送信号).然后,当向条件变量发送信号或广播时,等待列表上的一个或多个线程将被唤醒,该线程的互斥锁将再次被神奇地锁定.
您通常会看到以下带有条件变量的操作,说明它们是如何工作的.下面的示例是一个工作线程,它通过一个条件变量的信号获得工作.
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
do the work.
unlock mutex.
clean up.
exit thread.
只要等待返回时有一些可用的,工作就在这个循环中完成.当线程被标记为停止工作时(通常由另一个线程设置退出条件,然后启动条件变量以唤醒该线程),循环将退出,互斥锁将解锁,该线程将退出.
上面的代码是单用户模式,因为在工作完成时互斥锁保持锁定.对于多消费者变体,您可以使用example:
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
copy work to thread local storage.
unlock mutex.
do the work.
lock mutex.
unlock mutex.
clean up.
exit thread.
这允许其他消费者在这个消费者工作的同时接受工作.
condition变量减轻了轮询某个条件的负担,而不是允许另一个线程在需要发生某些事情时通知您.另一个线程可以告诉该线程工作可用,如下所示:
lock mutex.
flag work as available.
signal condition variable.
unlock mutex.
通常被错误地称为虚假唤醒的绝大多数情况通常都是因为多个线程在它们的pthread_cond_wait
调用(广播)内收到了信号,其中一个线程将带着互斥体返回,完成工作,然后重新等待.
然后,当没有工作要做时,第二个发出信号的线程可能会出现.因此,您必须有一个额外的变量来指示应该完成的工作(这里的condvar/mutex对本质上是受互斥保护的,但是其他线程需要在更改互斥之前锁定互斥).
从技术上讲,线程从等待状态返回而不被另一个进程踢(这是一个真正的虚假唤醒)是可能的,但是,在我多年从事pthreads的工作中,无论是在代码的开发/服务中,还是作为pthreads的用户,我从来没有收到过其中一个.也许这只是因为惠普有一个像样的实现:-)
在任何情况下,处理错误 case 的代码也会处理真正的虚假唤醒,因为不会为这些事件设置可用工作标志.