1.什么是条件变量
条件变量是维持线程同步的一种手段,当条件不满足时,线程会被自动阻塞,直到条件被触发为止。
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包含两个动作:1.一个或多个线程等待条件变量满足而被挂起;2.一个线程使条件成立(发出条件成立信号唤醒被阻塞的一个或多个线程)。
2.条件变量通常与互斥锁配合使用,为什么?互斥锁保护的是什么?
先来看一个条件变量的使用场景:
等待条件变量函数原型:
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
void *func(void *arg){ pthread_mutex_lock(&mutex); while(cond_is_false) //条件不满足,wait { pthread_cond_wait(&cond, &mutex); } //... pthread_mutex_unlock(&mutex); return (void *)0;}
mutex保护的是什么?
不是条件变量本身cond,而是确定条件变量是否成立的线程间共享的全局变量,当mutex被lock后,可以放心的去判断全局变量,而不用担心在这期间被其他线程改变其状态。当条件不满足时,该线程首先unlock了mutex,线程被挂起(以上两步操作在pthread_cond_wait中完成,两步操作一块完成(保证原子性)),当mutex被unlock后,其他线程就有机会修改全局变量使条件变量满足,从而发送条件成立信号,调用pthread_cond_signal,唤醒在pthread_cond_wait中仍在被阻塞的线程,使其从pthread_cond_wait中返回,在返回前需要再次lock mutex。
pthread_cond_wait的工作流程可总结为:
1.unlock mutex;
2.waiting;
3.条件满足时lock mutex返回。1和2在一起完成时原子性的。
3.为什么使用while而不是if?
- 因为pthread_cond_wait函数返回并不意味着一定是条件满足(被其他线程的pthread_cond_signal唤醒),而有可能是意外返回。
- 【个人理解,不一定正确】在某线程A发送条件满足信号调用pthread_cond_signal、unlock mutex后,到从waiting中唤醒的线程B lock mutex之间,可能会有其他线程C先一步lock mutex而导致条件变量不满足。因此等到被唤醒的线程B lock mutex后需再次判断条件是否真的满足。
4.为什么unlock与wait操作要在原子操作内进行?
如果不是原子操作,先unlock mutex,再wait(在wait时条件成立可被唤醒)。如果发生以下情况:在unlock之后,wait之前,有其他线程获取到mutex,使条件变量满足,并发出signal,而原线程因为还没wait而错过这个信号。
5.条件变量使用规范
等待条件:
pthread_mutex_lock(&mutex);while(条件为假){ pthread_cond_wait(&cond, &mutex);}修改条件pthread_mutex_unlock(&mutex);
条件满足时唤醒:
pthread_mutex_lock(&mutex);设置条件为真pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);
参考: