为什么在调用pthread_cond_wait
之前需要锁定互斥锁?
另外,在调用pthread_cond_signal
之前是否需要锁定(在同一个互斥锁上)?
感谢您的帮助。
答案 0 :(得分:26)
为什么在调用pthread_cond_wait之前需要锁定互斥锁?
因为否则会有不可避免的竞争条件。
互斥锁可以保护共享状态。条件变量与状态上的某个谓词(“条件”)相关联。基本的想法是你想要:
1)检查谓词
2)如果谓词为假,则进入睡眠状态直到它变为真
在并发系统中,某些线程总是可以在(1)和(2)之间使谓词成立。为了避免这种竞争,你必须在(1)之前持有一个互斥锁,你必须在执行(2)时原子地释放它。
例如,对于队列,谓词可能是“队列不为空”。但是在你检查队列是否为空的时间和你进入休眠状态的时间之间,其他一些线程可能会在队列中添加一些东西。
因此,您必须在检查谓词时以及在调用pthread_cond_wait时保持互斥锁。
另外,在调用pthread_cond_signal之前是否需要锁定(在同一个互斥锁上)?
据我所知,这没有根本问题;它只会引入潜在的低效率。
在这里,无论您正在修改哪个共享状态(从而使谓词成立)都必须受互斥锁保护。因此,只要您希望发出信号,您就必须已经拥有互斥锁。
如果在发出条件信号之前释放互斥锁,则由于某些其他线程的操作,谓词之间可能会变为假。这种竞争不会导致失败,因为等待条件的任何线程必须在继续之前检查谓词...但为什么要解决这个问题呢?
底线:只需按照说明操作即可,您甚至不必考虑这些问题。 : - )
答案 1 :(得分:1)
条件变量用于在您期望更改的条件下进行同步。锁定确保:
不使用互斥锁的条件系统会更脆弱。
答案 2 :(得分:1)
条件变量的全部要点是允许线程通知受互斥锁保护的数据结构的变化,例如:您可能希望在队列不再为空时收到通知,因此您以原子方式释放互斥锁并等待条件变量,并且当新元素排队时,您将被唤醒并使用互斥锁处理新元素。
与Java的监视器不同,pthread_cond_{signal,broadcast}()
不需要保留互斥锁。当没有线程在等待该条件变量时,条件变量的信号丢失,但这不应该产生那么大的差异,因为如果生产者在消费者之前开始运行,信号也可能丢失。