如何使用条件变量
Linux编程接口一书中有一段代码(生产者/消费者)来展示条件变量如何工作:
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int avail = 0;
while (TRUE) {
s = pthread_mutex_lock(&mtx);
while (avail == 0) { /* Wait for something to consume */
s = pthread_cond_wait(&cond, &mtx);
}
while (avail > 0) { /* Consume all available units */
avail--;
}
s = pthread_mutex_unlock(&mtx);
}
Why we use pthread_mutex_lock
in while
?为什么我们不在 if
中使用它?
The Linux Programming Interface book has a piece of code (producer/consumer) to show how condition variable works:
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int avail = 0;
while (TRUE) {
s = pthread_mutex_lock(&mtx);
while (avail == 0) { /* Wait for something to consume */
s = pthread_cond_wait(&cond, &mtx);
}
while (avail > 0) { /* Consume all available units */
avail--;
}
s = pthread_mutex_unlock(&mtx);
}
Why we use pthread_mutex_lock
in while
? why we don't use it in an if
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因为 pthread_cond_signal() 允许唤醒多个正在等待的线程条件变量。因此,一旦唤醒,您必须仔细检查条件,因为其他线程可能已经唤醒并在您之前更改了它。
如果您知道只有一个线程在等待,并且您确定将来没有人会修改程序中其他位置的代码来添加另一个等待的线程,那么您可以使用
if
。但你永远无法确定这一点,因此请始终使用while
。[更新]
正如 ninjalj 在评论中指出的那样,我的答案不完整,因为没有提到“虚假唤醒”。例如,POSIX 标准明确规定,如果等待线程接收到信号(例如通过kill()),即使没有其他线程向条件变量发出信号,pthread_cond_wait() 也可以返回0。关于等待线程是否可以无缘无故地被唤醒,标准是不明确的(在我看来)......但底线是:始终使用
while
,而不是if
。Because pthread_cond_signal() is allowed to wake up more than one thread waiting on the condition variable. Therefore you must double-check the condition once you wake up, because some other thread might have woken up and changed it ahead of you.
If you know you have just one thread waiting, and you are sure nobody in the future will ever modify code elsewhere in the program to add another thread waiting, then you can use
if
. But you never know that for sure, so always usewhile
.[update]
As ninjalj points out in a comment, my answer is incomplete for failing to mention "spurious wakeups". For example, the POSIX standard makes it clear that if the waiting thread receives a signal (e.g. via kill()), pthread_cond_wait() can return 0 even if no other thread signaled the condition variable. The standard is ambiguous (in my view) as to whether the waiting thread can be woken up for no reason at all... But the bottom line is: Always use
while
, notif
.