一.生产者消费者模型
设计模式:针对典型的应用场景设计的解决方案
应用场景: 大量的数据产出以及处理的场景
优点: 解耦合,支持忙闲不均,支持并发
- 解耦合:模块分离,降低功能耦合度
- 支持忙闲不均: 中间缓冲区队列,在压力大的时候缓冲大量数据,然后慢慢处理
- 支持并发: 支持多对多,前提是中间缓冲区的操作必须是线程安全的
并发与并行的区别:
- 并发:有处理多个任务的能力,但不一定要同时
- 并行:有同时处理多个任务的能力
一个场所,两种角色,三种关系.
最关键的实现:场所(线程安全的数据队列(缓冲区))
实现一个线程安全的数据队列(缓冲区),创建两种角色线程各自完成队列访问.
二.互斥锁+条件变量实现生产者消费者模型
//阻塞队列
class BlockQueue{
public:
BlockQueue(int cap)
:_capacity(cap)
{
pthread_mutex_init(&_mutex,NULL);
pthread_cond_init(&_cond_cus,NULL);
pthread_cond_init(&_cond_pro,NULL);
}
bool Push(const int date){
pthread_mutex_lock(&_mutex); //加锁
while(_queue.size() == _capacity){
pthread_cond_wait(&_cond_pro,&_mutex);
}
_queue.push(date);
pthread_mutex_unlock(&_mutex);
pthread_cond_broadcast(&_cond_cus); //唤醒所有消费者线程
return true;
}
bool Pop(int* buf){
pthread_mutex_lock(&_mutex);
while(_queue.empty() == true){
//当队列为空,则等待
pthread_cond_wait(&_cond_cus,&_mutex);
}
*buf = _queue.front();
_queue.pop();
pthread_mutex_unlock(&_mutex);
pthread_cond_broadcast(&_cond_pro); //唤醒所有生产者线程
return true;
}
~BlockQueue(){
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond_cus);
pthread_cond_destroy(&_cond_pro);
}
private:
queue<int> _queue;
int _capacity;
pthread_mutex_t _mutex;
pthread_cond_t _cond_cus;
pthread_cond_t _cond_pro;
};
三.信号量实现生产者消费者模型
class RingQueue{
public:
RingQueue(int cap)
:_list(cap)
,_capacity(cap)
,_read_step(0)
,_write_step(0)
{
sem_init(&_sem_lock,0,1);
sem_init(&_sem_idle,0,cap);
sem_init(&_sem_data,0,0);
}
~RingQueue(){
sem_destroy(&_sem_lock);
sem_destroy(&_sem_idle);
sem_destroy(&_sem_data);
}
bool Push(const int data){
sem_wait(&_sem_idle); //有空闲空间返回,没有则阻塞
sem_wait(&_sem_lock); //加锁
_list[_write_step] = data; //插入数据
_write_step = (_write_step+1)%_capacity; //更新_write_step
sem_post(&_sem_lock); //解锁
sem_post(&_sem_data); //数据资源+1,唤醒一个消费者
return true;
}
bool Pop(int* buf){
sem_wait(&_sem_data); //判断:有数据资源则返回,没有则阻塞
sem_wait(&_sem_lock);//加锁
*buf = _list[_read_step]; //获取数据
_read_step = (_read_step+1)%_capacity; //更新_read_step
sem_post(&_sem_lock);//解锁
sem_post(&_sem_idle); //空闲位置+1,唤醒一个生产者
return true;
}
private:
vector<int> _list;
int _capacity;
int _read_step;
int _write_step;
sem_t _sem_lock; //用于实现互斥
sem_t _sem_idle; //空闲资源计数:生产者能否入队数据的依据
sem_t _sem_data; //数据资源个数:消费者能否获取数据的依据
};