Linux:多线程-实现生产者与消费者模型


生产者消费者模型

理解

生产者消费者模型就像生活中的中介公司,他提供了一个生产者(卖方)和消费者(买方)的平台。
让生产者不需要操心资源的生产的快慢,让消费者不用担心资源的来源。保证了“交易”的达成。

优点

  1. 解耦合:消费者和生产不需要对数据进行交互
  2. 可并发:不同类型线程可以同时对缓冲队列进行操作
  3. 支持忙闲不均:即生产者与消费者的快慢程度不一

特点

一个场所:指缓冲区
两个对象:生产者和消费者
三种关系:

1.生产者与生产者之间互斥
2.消费者与消费者之间互斥
3.生产者与消费者之间同步

实现

使用信号量实现

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <vector>
#include <semaphore.h>
using namespace std;
#define max_queue 10

//模拟一个阻塞队列的生产者消费者模型
class BlockQueue
{
    private:
        vector<int> queue;
        int capacity;
        int _step_read;
        int _step_write;
        sem_t con_lock;
        sem_t pro_lock;
        sem_t sem_con;
        sem_t sem_pro;
    public:
        BlockQueue(int max_q = max_queue):capacity(max_q),queue(max_q),_step_read(0),_step_write(0)
        {
            sem_init(&con_lock,0,1);
            sem_init(&pro_lock,0,1);
            sem_init(&sem_con,0,0);
            sem_init(&sem_pro,0,max_q);
        }
        ~BlockQueue()
        {
            sem_destroy(&con_lock);
            sem_destroy(&pro_lock);
            sem_destroy(&sem_con);
            sem_destroy(&sem_pro);
        }
        bool queue_push(int &data)
        {
            //1.使用信号量等待,判断是否有位置可插入数据
            sem_wait(&sem_pro);
            //2.先上锁
            //这里的锁目的是为了保护数据访问的,不能放在条件判断之前
            //如果放在信号量判断之前,若消费者信号量阻塞,则会产生死锁
            sem_wait(&pro_lock);
            //3.插入数据
            queue[_step_write]=data;
            //求余操作保证_step_write的范围
            _step_write = (_step_write +1 )% capacity;
            //4.唤醒消费者进行取数据
            sem_post(&sem_con);
            //5.解锁
            sem_post(&pro_lock);
        }
        bool queue_pop(int &data)
        {
            //1.使用信号量等待,判断是否还有资源可以获取
            sem_wait(&sem_con);
            //2.上锁//这里的上锁目的是和相同线程间进行互斥
            //本来应该不同角色设置一把锁,如果是多核CPU就能实现并发
            sem_wait(&con_lock);
            //3.进行获取数据操作
            data = queue[_step_read];
            _step_read = (_step_read + 1)% capacity;
            //4.唤醒生产者可以进行数据的插入了
            sem_post(&sem_pro);
            //5.解锁
            sem_post(&con_lock);
        }
};
void *thr_con(void *arg)
{
    BlockQueue *queue = (BlockQueue*)arg;
    while(1)
    {
        int data;
        queue->queue_pop(data);
        printf("**get a data %d \n",data);
    }
    return NULL;
}
void *thr_pro(void *arg)
{
    BlockQueue *queue = (BlockQueue*)arg;
    int data = 0;
    while(1)
    {
        queue->queue_push(data);
        printf("--push a data %d \n",data++);
    }
    return NULL;
}
#define MAX_THR 4
int main()
{
    int ret;
    pthread_t ctid[MAX_THR],ptid[MAX_THR];
    
    BlockQueue _queue;
    for(int i=0; i<MAX_THR; i++)
    {
       ret= pthread_create(&ctid[i],NULL,thr_con,(void*)&_queue);
       if(ret!=0)
       {
           printf("create thread error\n");
           return -1;
       }
    }
    for(int i=0; i<MAX_THR; i++)
    {
       ret= pthread_create(&ptid[i],NULL,thr_pro,(void*)&_queue);
       if(ret!=0)
       {
           printf("create thread error\n");
           return -1;
       }
    }
    for(int i=0; i<MAX_THR; i++)
    {
        pthread_join(ctid[i],NULL);
        pthread_join(ptid[i],NULL);
    }
    return 0;
}


使用条间变量和互斥锁实现

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <queue>
using namespace std;

#define MAX_THR 4
class BlockQueue
{
    private:
        std::queue<int> _queue;//设置动态增长队列
        int _capacity;//确定队列的最大容量
        pthread_cond_t _cond_consumer;//消费者等待队列
        pthread_cond_t _cond_productor;//生产者等待队列
        pthread_mutex_t con_mutex;//设置互斥锁
        pthread_mutex_t pro_mutex;//设置互斥锁
    public:
        BlockQueue(int max_queue = 10):_capacity(max_queue) 
        {
            pthread_cond_init(&_cond_consumer,NULL);
            pthread_cond_init(&_cond_productor,NULL);
            pthread_mutex_init(&con_mutex,NULL);
            pthread_mutex_init(&pro_mutex,NULL);
        }
        ~BlockQueue()
        {
            pthread_cond_destroy(&_cond_consumer);
            pthread_cond_destroy(&_cond_productor);
            pthread_mutex_destroy(&con_mutex);
            pthread_mutex_destroy(&pro_mutex);
        }
        //提供给生产者的接口,数据入队
        bool queue_push(int &data)
        {
            pthread_mutex_lock(&pro_mutex);
            while(_queue.size() == _capacity)//判断队列节点是否添加满了
            {
                pthread_cond_wait(&_cond_productor,&pro_mutex);
            }
            _queue.push(data);
            pthread_mutex_unlock(&pro_mutex);
            pthread_cond_signal(&_cond_consumer);
            return true;
        }
        //提供给消费者的接口————数据出口
        bool queue_pop(int &data)
        {
            pthread_mutex_lock(&con_mutex);
            while(_queue.empty())
            {
                pthread_cond_wait(&_cond_consumer,&con_mutex);
            }
            data=_queue.front();
            _queue.pop();
            pthread_mutex_unlock(&con_mutex);
            pthread_cond_signal(&_cond_productor);
            return true;
        }

};
void *thr_consumer(void *arg)
{
    BlockQueue* b=(BlockQueue*)arg;
    while(1)
    {
        int data;
        b->queue_pop(data);
        printf("i get a data %d\n",data);
    }
    return NULL;
}
void *thr_productor(void *arg)
{
    int data = 0;
    BlockQueue* b=(BlockQueue*)arg;
    while(1)
    {
        b->queue_push(data);
        printf("i put a data %d\n",data++);
    }
    return NULL;
}
int main()
{
    pthread_t ctid[MAX_THR],ptid[MAX_THR];
    BlockQueue queue;
    for(int i=0;i<MAX_THR;i++)
    {
        int ret=pthread_create(&ctid[i],NULL,thr_consumer,(void*)&queue);
        if(ret!=0)
        {
            printf("create thr error\n");
            return -1;
        }
    }
    for(int i=0;i<MAX_THR;i++)
    {
        int ret=pthread_create(&ctid[i],NULL,thr_productor,(void*)&queue);
        if(ret!=0)
        {
            printf("create thr error\n");
            return -1;
        }
    }
    for(int i=0;i<MAX_THR;i++)
    {
        pthread_join(ptid[i],NULL);
        pthread_join(ctid[i],NULL);
    }
    return 0;
}


发布了35 篇原创文章 · 获赞 13 · 访问量 2113

猜你喜欢

转载自blog.csdn.net/weixin_42458272/article/details/103340479