条件变量
条件变量
条件变量简介
条件变量(condition variable)是为了等待某个条件成立而设计,提供一种线程间通知机制,在条件成立之前,等待线程进入睡眠状态,当某个条件成立时,信号端发射signal/broadcast来“唤醒”等待线程。
pthread条件变量相关的函数主要有以下5个:
#include <pthread.h>
int pthread_cond_init(pthread_cond_t* cond, const pthread_condattr* cond_attr);
int pthread_cond_destroy(pthread_cond_t* cond);
int pthread_cond_broadcast(pthread_cond_t* cond);
int pthread_cond_signal(pthread_cond_t* cond);
int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex* mutex);
以上函数均以返回0表示成功,非0表示出错。
条件变量的资源申请分为静态和动态两种,分别为:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
// 使用宏将条件变量各个字段初始化为0- 调用
pthread_cond_init/pthread_cond_destroy
为动态初始化和销毁条件变量资源
条件变量的使用
条件变量需结合互斥量(mutex)一起使用。pthread_cond_wait
等待条件成立时需配备一个mutex来保护等待操作的原子性,调用pthread_cond_wait
之前,需确保mutex已经加锁,否则将导致不可预期行为。pthread_cond_wait
函数执行时,首先将mutex解锁,然后判断条件是否成立,待该等待函数成功返回后,mutex重新被加锁。
条件变量是一个或多个线程等待某个布尔表达式为真,下面推荐打开条件变量正确的姿势。
对于wait端:
- 必须与mutex一起使用,该布尔表达式的读写操作受此mutex保护;
- 在调用
pthread_cond_wait
之前必须先对mutex加锁; - 把判断布尔条件和wait操作放在
while
循环中,而非if
语句中。
对于signal/broadcast端:
- 不一定在mutex上锁的情况下调用signal;
- 在signal之前一般需要修改布尔表达式;
- 修改布尔表达式需要mutex保护;
- 注意区分signal和broadcast。
MutexLock mtx;
Condition cond(mtx);
std::deque<int> queue;
// wait端
int Dequeue() {
MutexLockGuard lk(mtx);
while(queue.empty()) {
cond.Wait();
}
assert(!queue.empty());
int top = queue.front();
queue.pop_front();
return top;
}
// signal端
void Enqueue(int x) {
MutexLockGuard lk(mtx);
queue.push_back(x);
cond.notify();
}
参考:
【1】《Linux多线程服务器编程》——陈硕
【2】《UNP》
总结积累,分享交流