Linux 何时使用 pthread 条件变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20772476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use pthread condition variables?
提问by MichaelMoser
pthread question:
线程问题:
it appears that a condition variable only works if pthread_cond_wait is called before the other thread calls pthread_cond_notify. If notify somehow happens before wait then wait will be stuck.
似乎只有在其他线程调用 pthread_cond_notify 之前调用 pthread_cond_wait 时,条件变量才起作用。如果在等待之前通知以某种方式发生,那么等待将被卡住。
My question is: when should condition variables be used?
我的问题是:什么时候应该使用条件变量?
The scheduler can preempt threads and a notify may happen before wait.
调度程序可以抢占线程,并且在等待之前可能会发生通知。
Waiting on semaphores does not have this problem -- these have a counter.
等待信号量没有这个问题——它们有一个计数器。
When is a conditional variable better than a semaphore?
什么时候条件变量比信号量更好?
Here is a test:
这是一个测试:
File condvar.c
文件 condvar.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
// test of conditional variables;
// if cond-var is notified before wait starts, then wait never wakes up !!!
// better to use semaphores than this crap.
pthread_mutex_t cond_var_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
int wait_first = 1;
void *tfunc(void *arg)
{
(void) arg;
if (!wait_first)
sleep(1);
fprintf(stderr,"on enter cond_var_lock %lx\n", pthread_self());
pthread_mutex_lock( &cond_var_lock);
fprintf(stderr,"before pthread_cond_wait %lx\n", pthread_self());
pthread_cond_wait( &cond_var, &cond_var_lock);
fprintf(stderr,"after pthread_cond_wait %lx\n", pthread_self());
pthread_mutex_unlock( &cond_var_lock);
fprintf(stderr,"after exit cond_var_lock %lx\n", pthread_self());
return 0;
}
int main(int argc, char *argv[])
{
pthread_t th;
if (argc > 0)
wait_first = atoi( argv[1] );
if (wait_first)
{
fprintf(stderr,"********* Wait first ***********\n");
} else {
fprintf(stderr,"********* Notify first *********\n");
}
pthread_create( &th, 0, tfunc, 0 );
if (wait_first)
{
sleep(1);
}
fprintf(stderr, "! on enter cond_var_lock %lx\n", pthread_self());
pthread_mutex_lock( &cond_var_lock);
fprintf(stderr, "! before pthread_cond_signal %lx\n", pthread_self());
pthread_cond_signal( &cond_var );
fprintf(stderr, "! after pthread_cond_signal %lx\n", pthread_self());
pthread_mutex_unlock( &cond_var_lock);
fprintf(stderr, "! after exit cond_var_lock %lx\n", pthread_self());
sleep(5);
return 0;
}
File test.sh
文件 test.sh
#!/bin/sh
set -e
set -x
gcc condvar.c -o condvar -lpthread
./condvar 1
./condvar 0
Test output
测试输出
Output:
+ gcc condvar.c -o condvar -lpthread
+ ./condvar 1
********* Wait first ***********
on enter cond_var_lock b7779b70
before pthread_cond_wait b7779b70
! on enter cond_var_lock b777a6c0
! before pthread_cond_signal b777a6c0
! after pthread_cond_signal b777a6c0
! after exit cond_var_lock b777a6c0
after pthread_cond_wait b7779b70
after exit cond_var_lock b7779b70
+ ./condvar 0
********* Notify first *********
! on enter cond_var_lock b785c6c0
! before pthread_cond_signal b785c6c0
! after pthread_cond_signal b785c6c0
! after exit cond_var_lock b785c6c0
on enter cond_var_lock b785bb70
before pthread_cond_wait b785bb70
采纳答案by chill
Condition variables should be used as a place to wait and be notified. They are not the condition itself and they are not events. The condition is contained in the surrounding programming logic. The typical usage pattern of condition variables is
条件变量应该用作等待和通知的地方。它们不是条件本身,也不是事件。该条件包含在周围的编程逻辑中。条件变量的典型使用模式是
// safely examine the condition, prevent other threads from
// altering it
pthread_mutex_lock (&lock);
while ( SOME-CONDITION is false)
pthread_cond_wait (&cond, &lock);
// Do whatever you need to do when condition becomes true
do_stuff();
pthread_mutex_unlock (&lock);
On the other hand, a thread, signaling the condition variable, typically looks like
另一方面,发送条件变量信号的线程通常看起来像
// ensure we have exclusive access to whathever comprises the condition
pthread_mutex_lock (&lock);
ALTER-CONDITION
// Wakeup at least one of the threads that are waiting on the condition (if any)
pthread_cond_signal (&cond);
// allow others to proceed
pthread_mutex_unlock (&lock)