Linux组件封装之二:Condition

本博文讨论Linux中的条件变量Condition的封装;

条件变量Condition 主要描述的是 线程间 的同步,即协作关系

Linux中的条件变量通常涉及以下几个函数:

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_destroy(pthread_cond_t *cond);

 

一、条件变量类(Condition):

 1 #ifndef CONDITION_H_
 2 #define CONDITION_H_
 3 
 4 #include "NonCopyable.h"
 5 #include "MutexLock.h"
 6 #include <pthread.h>
 7 
 8 class Condition:NonCopyable //私有继承
 9 {
10     public:        
11         Condition(MutexLock &mutex);
12         ~Condition();
13 
14         void wait();//等待
15         void signal();//发送信号
16     private:
17         pthread_cond_t cond_;
18         MutexLock &mutex_; //wait函数的参数
19 };
20 
21 Condition::Condition(MutexLock &mutex)
22     :mutex_(mutex)
23 {
24     pthread_cond_init(&cond_, NULL);
25 }
26 
27 Condition::~Condition()
28 {
29     pthread_cond_destroy(&cond_);
30 }
31 
32 void Condition::wait()
33 {
34     pthread_mutex_t  lock = mutex_.getMutex(); 
35     pthread_cond_wait(&cond_, &lock);
36 }
37 
38 void Condition::signal()
39 {
40     pthread_cond_signal(&cond_);
41 }
42 #endif

这里要注意几点:

1)、wait必须在加锁的条件下方可使用;

2)、signal函数 一次唤醒一个线程,通常用来通知资源可用

3)、broadcast函数一次通知多个线程,用来通知状态的改变,滥用其,将会导致“惊群”问题;

 

使用wait函数时,必须使用while 循环原因如下

1、采用 if 语句,最多只能判断一次;

2、为了描述方便,我们假设,这里有 5 个生产者(producer), 3 个消费者(consumer),缓冲区中最多能盛放 10 个产品;

a)假设现在缓冲区中已经存在10 个产品,如果再用生产者A抢到这把锁,就会调用 wait函数, 将producer函数阻塞,向consumer发送信号并释放该锁,

b)这时有一个consumer抢到 该锁,自然会消费一个产品,并释放该 锁,这时产品数还有 9 个;

c)由于抢锁 是不排队的,因此有可能是除了 A 之外的 producer(假设为B) 抢到锁,由于缓冲区未满(9个),因此会生产一个产品,这时缓冲区已满;

d)还是由于 抢锁是不排队的,这时有可能 A 又重新获得该锁,由于 if 只会判断一次, 而且也已近执行过,故,A生产者会生产一个产品,由于缓冲区已满,

这时如果再生产产品的话,就会造成溢出。

e)若采用 whilt 循环, A 若获得该锁,则会先判断 缓冲区的状态(是否已满),如果已满,则又会进入阻塞状态,不会造成溢出。

3、为了防止broadcast的干扰:如果有且仅有一个资源,使用broadcast会唤醒所有等待的线程,那么多个线程被唤醒,但最终只有一个能拿到资源,这就是所谓的“惊群效应”。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。