生产者消费者模型的两种实现方式 | 互斥锁+条件变量实现 信号量实现

一.生产者消费者模型

设计模式:针对典型的应用场景设计的解决方案

应用场景: 大量的数据产出以及处理的场景

优点: 解耦合,支持忙闲不均,支持并发

  • 解耦合:模块分离,降低功能耦合度
  • 支持忙闲不均: 中间缓冲区队列,在压力大的时候缓冲大量数据,然后慢慢处理
  • 支持并发: 支持多对多,前提是中间缓冲区的操作必须是线程安全的

并发与并行的区别:

  • 并发:有处理多个任务的能力,但不一定要同时
  • 并行:有同时处理多个任务的能力

一个场所,两种角色,三种关系.

最关键的实现:场所(线程安全的数据队列(缓冲区))

实现一个线程安全的数据队列(缓冲区),创建两种角色线程各自完成队列访问.

二.互斥锁+条件变量实现生产者消费者模型

//阻塞队列
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; //数据资源个数:消费者能否获取数据的依据
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值