pthread问题:
似乎只有在其他线程调用pthread_cond_notify之前调用pthread_cond_wait时,条件变量才起作用。如果在等待之前以某种方式发生通知,则等待将卡住。
我的问题是: 什么时候应该使用条件变量?
调度程序可以抢占线程,并且在等待之前可能会发生通知。
等待信号量没有这个问题-它们有一个计数器。
什么时候条件变量比信号量更好?
这是一个测试:
#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; }
#!/bin/sh set -e set -x gcc condvar.c -o condvar -lpthread ./condvar 1 ./condvar 0
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
条件变量应该用作等待和通知的地方。它们不是条件本身,也不是事件。条件包含在周围的编程逻辑中。条件变量的典型用法是
// 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);
另一方面,发出信号通知条件变量的线程通常看起来像
// 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)