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

一.生产者消费者模型

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

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

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

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

并发与并行的区别:

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

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

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

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

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以和你讨论一下这个问题。生产者-消费者问题是一个著名的同步问题,解决此问题可以使用互斥条件变量信号等同步机制。这里我们使用信号来解决该问题。 在 Python 中,我们可以使用 threading 模块来创建线程,并使用 queue 模块中的 Queue 类来实现生产者-消费者模型。下面是一个实现生产者-消费者模型的示例代码: ```python import threading import time import random import queue # 初始化互斥、空位信号和满位信号 mutex = threading.Lock() empty = threading.Semaphore(5) full = threading.Semaphore(0) # 创建队列 q = queue.Queue() # 生产者函数 def producer(): while True: # 等待空位信号 empty.acquire() # 获取互斥 mutex.acquire() # 生产数据 item = random.randint(0, 10) q.put(item) print("生产者生产了数据:", item) # 释放互斥 mutex.release() # 发送满位信号 full.release() time.sleep(1) # 消费者函数 def consumer(): while True: # 等待满位信号 full.acquire() # 获取互斥 mutex.acquire() # 消费数据 item = q.get() print("消费者消费了数据:", item) # 释放互斥 mutex.release() # 发送空位信号 empty.release() time.sleep(1) # 创建生产者消费者线程 p = threading.Thread(target=producer) c = threading.Thread(target=consumer) # 启动线程 p.start() c.start() # 等待线程结束 p.join() c.join() ``` 在上面的代码中,我们使用了一个队列来存储生产者生产的数据,使用互斥来保证同一时间只有一个线程可以访问队列,使用空位信号来控制生产者线程的运行,使用满位信号来控制消费者线程的运行。 在生产者函数中,我们首先等待空位信号,从而保证队列中有足够的空位可以存储生产者生产的数据。然后获取互斥,生产数据并将其放入队列中,最后释放互斥并发送满位信号。 在消费者函数中,我们首先等待满位信号,从而保证队列中有足够的数据可以被消费者消费。然后获取互斥,从队列中获取数据并进行消费,最后释放互斥并发送空位信号。 通过使用互斥、空位信号和满位信号,我们可以很好地解决生产者-消费者问题,并保证线程的同步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值