最近看到了对于pthread_cond_t条件变量这样的解释:
Recommendation: Using a WHILE loop instead of an IF statement (see watch_count routine in example below) to check the waited for condition can help deal with several potential problems, such as:
比如在生产消费者问题中:
while(condd.ready == 1)//已生产,还没消费完,此时producer休眠
pthread_cond_wait(&condd.cond, &condd.lock);
如果用if,那么100个线程执行这段代码,都被唤醒,后果是每个线程都顺序的认为条件满足了,实际上条件并不满足(生产者生产出来的一件消费品已经被第一个线程消费了)
下面的建议是说:在判断条件是否满足的时候使用while而不是使用if,因为
1 有可能多个线程等待一个条件,而当条件满足时他们去争抢获得mutex,最后只有一个成功锁住mutex,如果使用if那么这些线程都会认为自己条件满足了,但其实是被其他线程抢夺了.
2 有可能因为程序的bug线程获得了信号
3 pthreads库认为虚假的唤醒一个等待线程并不违反标准。
在陈硕的书里这样总结正确使用条件变量:
条件变量只有一种正确使用的方式,几乎不可能用错。对于 wait 端:
1. 必须与 mutex 一起使用,该布尔表达式的读写需受此 mutex 保护。
2. 在 mutex 已上锁的时候才能调用 wait()。
3. 把判断布尔条件和 wait() 放到 while 循环中。
对于 signal/broadcast 端:
1. 不一定要在 mutex 已上锁的情况下调用 signal (理论上)。
2. 在 signal 之前一般要修改布尔表达式。
3. 修改布尔表达式通常要用 mutex 保护(至少用作 full memory barrier)。
4. 注意区分 signal 与 broadcast:“broadcast 通常用于表明状态变化,signal 通常用于表示资源可用。(broadcast should generally be used to indicate state change rather than resource availability。)”