# 为何需要条件变量
# 定义
## 一定需要while 和 全局变量 done吗
## 一定需要锁吗
# 生产者和与消费者
## 代码分析
### A Bronken Solution - CV
### Better, But still broken , while , NOT if
### The Single Buffer Producer/Cosumer Solution
# 覆盖性条件
为何需要条件变量(Condition Variables)
锁并不是唯一的多线程通信的方案。在其他一些case中,比如父进程在执行后续操作之前,要检查子进程是否结束。也就是说父进程被block,子进程complete后,需要通知父进程,然后父进程才能继续运行下去。
volatile int done = 0;
void * child(void * arg) {
printf("child\n");
done = 1;
return NULL:
}
int main(int argc, char ** argv) {
printf("parent: begin\n");
pthread_t c;
pthread_create(&c, NULL, child, NULL); // create child
while (done == 0)
; // spin
printf("parent:end \n");
return 0;
}
在父进程中采用自旋的方式,其实非常低效,浪费CPU周期。而且有时候正确性也不能保证。此时在这种A线程需要等待B线程的通知才能进行下去的情况,我们可以使用条件变量,condition variable.
定义
条件变量是一个队列,线程可以将他们自己放入其中,睡眠,等待条件满足被唤醒(当然被唤醒可以不止一个)。
变量类型:pthread_cond_t c
操作动作(Posix call):**pthread_cond_wait(pthread_cond_t c, pthread_mutex_t m)
其实就是wait + signal 的操作
int done = 0;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c = PTHREAD_COND_INITIALIZER;
void * child(void * arg) {
printf("child\n");
thr_exit();
return NULL;
}
void thr_exit() {
pthread_mutex_lock(&m);
done = 1;
pthread_cond_signal(&c);
pthread_mutex_unlock(&m);
}
void thr_join() {
pthread_mutex_lock(&m);
while(done == 0)
pthread_cond_wait(&c, &m);
pthread_mutex_unlock(&m);
}
int main(int argc, char ** argv) {
printf("parent: begin\n");
pthread_t p ;
pthread_create(&p, NULL, child, NULL
thr_join();
printf("parent:end\n");
return 0;
}
wait 函数是携带一把锁的,在该线程wait之前,该线程是拿到这把锁的。调用wait时,该线程释放这把锁后,自行进入sleep队列。
如果该线程被唤醒,那么该线程一定已经再次 re-acuqire这把锁了。然后才从wait函数返回。
对于上面一段代码会有两种情况
- 情况1:
- 线程1在create 出线程2后,cpu调度,继续执行线程1