我正在阅读pthread.h;条件变量相关函数(如pthread_cond_wait(3))需要互斥体作为参数。为什么?据我所知,我将创建一个互斥锁 只是 为了用作该参数?那个互斥锁应该做什么?
pthread.h
pthread_cond_wait(3)
这只是条件变量(或最初)实现的方式。
互斥锁用于保护 条件变量本身 。这就是为什么在等待之前需要将其锁定的原因。
等待将“原子地”解锁互斥锁,允许其他人访问条件变量(用于信号)。然后当条件变量被发送或广播时,等待列表中的一个或多个线程将被唤醒,互斥锁将再次神奇地为该线程锁定。
您通常会看到以下带有条件变量的操作,说明它们是如何工作的。下面的例子是一个工作线程,它通过一个条件变量的信号来工作。
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.
如果等待返回时有一些可用的,则在此循环中完成工作。当线程被标记为停止工作时(通常由另一个线程设置退出条件然后踢条件变量以唤醒该线程),循环将退出,互斥锁将被解锁并且该线程将退出。
上面的代码是一个单消费者模型,因为互斥体在工作完成时保持锁定状态。对于多消费者变体,您可以使用, 例如 :
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.
这允许其他消费者在这个消费者工作时接收工作。
条件变量减轻了您轮询某些条件的负担,而是允许另一个线程在需要发生某些事情时通知您。另一个线程可以告诉该线程该工作可用,如下所示:
lock mutex. flag work as available. signal condition variable. unlock mutex.
通常被错误地称为虚假唤醒的绝大多数通常总是因为在它们的pthread_cond_wait调用(广播)中已发出多个线程的信号,一个线程将返回互斥锁,完成工作,然后重新等待。
pthread_cond_wait
然后当没有工作要做时,第二个信号线程可以出来。因此,您必须有一个额外的变量来指示应该完成的工作(这本来就是由 condvar/mutex 对在这里受到互斥保护的——但是,其他线程需要在更改互斥之前锁定互斥)。
从技术上讲 , 线程可以从条件等待中返回而不会被另一个进程踢(这是一个真正的虚假唤醒),但是,在我从事 pthreads 的所有这些年中,无论是在代码的开发/服务中还是作为用户其中,我从未收到过其中之一。也许这只是因为惠普有一个不错的实施:-)
在任何情况下,处理错误情况的相同代码也处理真正的虚假唤醒,因为不会为这些设置工作可用标志。