条件变量 condition variable
怎么用
man pthread_cond_init
man pthread_cond_wait
注意:
- 必须和mutex一起用,必须先锁住mutex,再wait,否则的行为是未定义的。
- 不是信号安全的。因此不要在信号的handler里用
- 用同一个mutex,否则行为未定义
如何实现无限缓冲区
假设只有一个消费者,一个生产者
// 生产者
lock(&mutex)
queue.push()
if (queue.size() == 1) {
pthread_cond_signal(&cond)
}
unlock(&mutex)
// 消费者
lock(&mutex)
while (queue.size() <= 0) {
pthread_cond_wait(&cond, &mutex);
}
item = queue.pop()
unlock()
假设有多个生产者,多个消费者,则pthread_cond_signal的时候,只能唤醒一个消费者,并发程度不够,必须要把所有消费者都用上才行。方法是:
1. 不判断,直接pthread_cond_signal.会有点overhead,不过如果没有线程在等待的话,这个函数也没干啥。
2. 判断size()==1时,pthread_cond_broadcast.问题是,虽然广播了,全唤醒了,但只有1个线程抢到了,其他还是继续sleep。
3. 自己维护正在sleep的消费者的个数,来决定调用几次pthread_cond_signal。增加了维护负担。
如何实现有限缓冲区
跟无限缓冲区相比,这回,两个线程都要做signal和wait。理论上,用一个条件变量仍然可以实现:
// 生产者
lock(&mutex)
while (queue.size() >= N){
pthread_cond_wait(&cond, &mutex)
}
queue.push()
if (queue.size() == 1) {
pthread_cond_signal(&cond)
}
unlock(&mutex)
// 消费者
lock(&mutex)
while (queue.size() <= 0){