多线程----生产者与消费者模型

生产者与消费者模型

在这里插入图片描述
一个场所,两种角色,三种关系
一个场所是指缓冲区
两种角色是指生产者和消费者
三种关系是指:
生产者与生产者的互斥关系
消费者与消费者的互斥关系
生产者与消费者的同步+互斥关系

生产者与消费者模型的优点:
1.解耦合:即不需要直接进行数据交互
2.支持并发:即多个线程可以同时操作场所
3.支持忙闲不均

三个优点都是通过这个场所来提供,但是因为多个角色有可能同时操作场所,所以要保证场所的操作安全

用阻塞队列+条件变量来模拟实现生产者消费者模型

#include <iostream>
#include <queue>
#include <pthread.h>
#define MAX_QUEUE   10
class BlockQueue
{   
    private:
        std::queue<int> _queue;
        int _capacity;//queue是动态增长的,需要限制队列中最大节点数量
        pthread_mutex_t _mutex;
        pthread_cond_t _cond_product;
        pthread_cond_t _cond_consumer;
    public:
	    //初始化
        BlockQueue(int cap = MAX_QUEUE):_capacity(cap) {
            pthread_mutex_init(&_mutex, NULL);
            pthread_cond_init(&_cond_product, NULL);
            pthread_cond_init(&_cond_consumer, NULL);
        }
        ~BlockQueue() {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_cond_product);
            pthread_cond_destroy(&_cond_consumer);
        }
		//生产者入队列
        bool QueuePush(int data) {
            pthread_mutex_lock(&_mutex);
            while(_queue.size() == _capacity) 
				//队列满,生产者等待
			{
                pthread_cond_wait(&_cond_product, &_mutex);
            }
            _queue.push(data);
            pthread_cond_signal(&_cond_consumer);
            pthread_mutex_unlock(&_mutex);
        }
		//消费者出队列
        bool QueuePop(int &data) {
            pthread_mutex_lock(&_mutex);
            while(_queue.empty()) 
				//队列空,消费者等待
			{
                pthread_cond_wait(&_cond_consumer, &_mutex);
            }
            data = _queue.front();//获取队首节点
            _queue.pop();
            pthread_cond_signal(&_cond_product);
            pthread_mutex_unlock(&_mutex);
        }
};
//生产者入口函数
void *thr_product (void *arg)
{
    BlockQueue *q = (BlockQueue*)arg;
    int i = 0;
    while(1) {
        q->QueuePush(i++);//将数据放入
        std::cout<<"productor:"<<pthread_self()<<"put data:" << i<<"\n";
    }
    return NULL;
}

//消费者入口函数
void *thr_consumer (void *arg)
{
    BlockQueue *q = (BlockQueue*)arg;//获取参数
    while(1) {
        int data;
        q->QueuePop(data);//将数据取出
        std::cout<<"consumer:"<<pthread_self()<<"get data:"<<data<<"\n";
    }
    return NULL;
}


int main()
{
    pthread_t con_tid[4], pro_tid[4];
    BlockQueue q;
    int ret;
	//分别创建四个生产者线程和四个消费者线程
    for (int i = 0; i < 4; i++) {
        ret = pthread_create(&con_tid[i], NULL, thr_consumer,(void*)&q);
        if (ret != 0) {
            std::cout<<"thread create error\n";
            return -1;
        }
    }
    for (int i = 0; i < 4; i++) {
        ret = pthread_create(&pro_tid[i], NULL, thr_product, (void*)&q);
        if (ret != 0) {
            std::cout<<"thread create error\n";
            return -1;
        }
    }
	
	//为了不让线程直接退出,在这里等待
    for (int i = 0; i < 4; i++) {
        pthread_join(con_tid[i], NULL);
    }
    for (int i = 0; i < 4; i++) {
        pthread_join(pro_tid[i], NULL);
    }
    return 0;
}

用环形队列+信号量来模拟实现生产者消费者模型

需要先实现一个环形队列,再用信号量实现互斥锁

class RingQueue
{
private:
     std:vector<int>_queue;
     int _capacity;
     int _read;     //读
     int _write;    //写
     sem_t lock;
     sem_t _idle_space;     //空闲空间大小,初始化为capacity,生产者在这个队列等待
     sem_t _data_space;     //队列中的数据个数,初始化为0,消费者在这个队列等待
public:
     QueuePush(int data);     //入队列
     QueuePop(int &data);     //出队列
}
#include <iostream>
#include <vector>
#include <pthread.h>
#include <semaphore.h>
#define MAX_QUEUE   10
class RingQueue
{
    private:
        std::vector<int> _queue;
        int _capacity;
        int _read;
        int _write;
        sem_t _lock;
        //生产者入队数据之前判断队列中是否有空闲空间;判断能否入队数据
        sem_t _idle_space;
        //消费者获取数据之前判断有数据的空间有多少判断能否获取数据
        sem_t _data_space;
    public:
        RingQueue(int maxque = MAX_QUEUE):_capacity(maxque), _queue(maxque)
        {    
            sem_init(&_lock, 0, 1);
            sem_init(&_idle_space, 0, _capacity);
            sem_init(&_data_space, 0, 0);
        }
        ~RingQueue(){
            sem_destroy(&_lock);
            sem_destroy(&_idle_space);
            sem_destroy(&_data_space);
        }
        bool QueuePush(int data) {
            sem_wait(&_idle_space);//判断是否有资源可以操作

            sem_wait(&_lock);//下方属于临界资源,需要被保护
            _queue[_write] = data;
            _write = (_write + 1) % _capacity;
            sem_post(&_lock);

            sem_post(&_data_space);//数据空间计数+1;唤醒消费者取数据
            
            return true;
        }
        bool QueuePop(int &data) {
            sem_wait(&_data_space);//通过数据空间计数判断是否有数据操作

            sem_wait(&_lock);
            data = _queue[_read];
            _read = (_read + 1) % _capacity;
            sem_post(&_lock);

            sem_post(&_idle_space);//空闲空间计数+1;唤醒生产者
            return true;
        }
};

//入队数据
void *productor(void  *arg)
{
    RingQueue *q = (RingQueue*)arg;
    int i = 0;
    while(1) {
        std::cout << "productor put a data: " << i<<std::endl;
        q->QueuePush(i++);
    }
    return NULL;
}
//出队数据
void *consumer(void  *arg)
{
    RingQueue *q = (RingQueue*)arg;
    while(1) {
        int data;
        q->QueuePop(data);
        std::cout << "consumer get a data: "<< data << std::endl;
    }
    return NULL;
}

int main()
{
    pthread_t p_tid[4], c_tid[4];//创建四个生产者和四个消费者线程
    RingQueue q;

    for (int i = 0; i < 4; i++) {
        int ret = pthread_create(&p_tid[i], NULL, productor, (void*)&q);
        if (ret != 0) {
            std::cout << "pthread productor create error\n";
            return -1;
        }
    }
    for (int i = 0; i < 4; i++) {
        int ret = pthread_create(&c_tid[i], NULL, consumer, (void*)&q);
        if (ret != 0) {
            std::cout << "pthread consumer create error\n";
            return -1;
        }
    }

    for(int i = 0; i < 4; i++) {
        pthread_join(c_tid[i], NULL);
    }
    for(int i = 0; i < 4; i++) {
        pthread_join(p_tid[i], NULL);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值