生产者消费者模型

生产者与消费者模型

一种特殊的设计模式

针对场景

有大量数据的产生以及处理的场景。

生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,
而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生
产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个
阻塞队列就是用来给生产者和消费者解耦的

生产者与消费者模型的优点

解耦合、支持并发、支持忙闲不均

实现

生产者与消费者无非就是两类执行流+线程安全的任务队列。

条件变量+互斥锁

#include <iostream>
#include <cstdio> 
#include <cstdlib> 
#include <queue>
#include <mutex>
#include <pthread.h>

#define MAXQ 10
class BlockQueue
{
    private:
        std::queue<int> _queue;
        int _capacity;
        pthread_mutex_t _mutex;
        pthread_cond_t _cond_pro;
        pthread_cond_t _cond_con;
    public:
        BlockQueue(int maxq = MAXQ):_capacity(maxq){
            pthread_mutex_init(&_mutex, NULL);
            pthread_cond_init(&_cond_pro, NULL);
            pthread_cond_init(&_cond_con, NULL);
        }
        ~BlockQueue() {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_cond_pro);
            pthread_cond_destroy(&_cond_con);
        }
        bool Push(int data){
            pthread_mutex_lock(&_mutex);
            while(_queue.size() == _capacity) {
                pthread_cond_wait(&_cond_pro, &_mutex);
            }
            _queue.push(data);
            pthread_mutex_unlock(&_mutex);
            pthread_cond_signal(&_cond_con);
            return true;
        }
        bool Pop(int *data) {
            pthread_mutex_lock(&_mutex);
            while(_queue.empty() == true) {
                pthread_cond_wait(&_cond_con, &_mutex);
            }
            *data = _queue.front();
            _queue.pop();
            pthread_mutex_unlock(&_mutex);
            pthread_cond_signal(&_cond_pro);
            return true;
        }
};

std::mutex g_mutex;
void *consumer(void *arg)
{
    BlockQueue *q = (BlockQueue*)arg;
    int data;
    while(1) {
        q->Pop(&data);
        printf("%p- pop data:%d\n", pthread_self(), data);
    }
    return NULL;
}
void *productor(void *arg)
{
    BlockQueue *q = (BlockQueue*)arg;
    int i = 0;
    while(1) {
        q->Push(i);
        printf("%p push data:%d\n", pthread_self(), i++);
    }
    return NULL;
}
int main()
{
    pthread_t ctid[4], ptid[14];
    int ret;
    BlockQueue q;

    for (int i = 0; i < 4; i++) {
        ret = pthread_create(&ctid[i], NULL, consumer, (void*)&q);
        if (ret != 0) {
            printf("thread create error\n");
            return -1;
        }
    }
    for (int i = 0; i < 14; i++) {
        ret = pthread_create(&ptid[i], NULL, productor, (void*)&q);
        if (ret != 0) {
            printf("thread create error\n");
            return -1;
        }
    }
    for (int i = 0; i < 4; i++) {
        pthread_join(ctid[i], NULL);
        pthread_join(ptid[i], NULL);
    }
    return 0;
}

信号量+环形队列

#include <iostream>
#include <cstdlib>
#include <vector>
#include <pthread.h>
#include <semaphore.h>

#define MAXQ 5

class RingQueue{
    private:
        std::vector<int> _arry;
        int _capacity;
        int _write_step;
        int _read_step;
        sem_t _sem_idle;//
        sem_t _sem_data;
        sem_t _sem_lock;
    public:
        RingQueue(int maxq = MAXQ):_arry(maxq),
        _capacity(maxq), _write_step(0), _read_step(0){
            //sem_init(信号量,1进程/0线程,初值)
            sem_init(&_sem_idle, 0, maxq);
            sem_init(&_sem_data, 0, 0);//初始没有数据
            sem_init(&_sem_lock, 0, 1);
        }
        ~RingQueue(){
            sem_destroy(&_sem_idle);
            sem_destroy(&_sem_data);
            sem_destroy(&_sem_lock);
        }
        bool Push(const int data){
            sem_wait(&_sem_idle);//空闲空间-1
            sem_wait(&_sem_lock);//加锁
            _arry[_write_step] = data;
            _write_step = (_write_step+1)%_capacity;
            sem_post(&_sem_lock);//解锁
            sem_post(&_sem_data);//数字资源+1
            return true;
        }
        bool Pop(int *data){
            sem_wait(&_sem_data);//数据资源-1
            sem_wait(&_sem_lock);//加锁
            *data = _arry[_read_step];
            _read_step = (_read_step+1)%_capacity;
            sem_post(&_sem_lock);//解锁
            sem_post(&_sem_idle);//空闲空间+1
            return true;
        }
};
void *consumer(void *arg)
{
    RingQueue *q = (RingQueue*)arg;
    int data;
    while(1) {
        q->Pop(&data);
        printf("%p- pop data:%d\n", pthread_self(), data);
    }
    return NULL;
}
void *productor(void *arg)
{
    RingQueue *q = (RingQueue*)arg;
    int i = 0;
    while(1) {
        q->Push(i);
        printf("%p push data:%d\n", pthread_self(), i++);
    }
    return NULL;
}
int main()
{
    pthread_t ctid[4], ptid[14];
    int ret;
    RingQueue q;

    for (int i = 0; i < 4; i++) {
        ret = pthread_create(&ctid[i], NULL, consumer, (void*)&q);
        if (ret != 0) {
            printf("thread create error\n");
            return -1;
        }
    }
    for (int i = 0; i < 4; i++) {
        ret = pthread_create(&ptid[i], NULL, productor, (void*)&q);
        if (ret != 0) {
            printf("thread create error\n");
            return -1;
        }
    }
    for (int i = 0; i < 4; i++) {
        pthread_join(ctid[i], NULL);
        pthread_join(ptid[i], NULL);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值