【Linux】生产者消费者模型

本文介绍了Linux中生产者消费者模型的概念及其在多线程编程中的应用。通过线程安全的队列实现,该模型能解耦合并支持并发。文章分析了生产者、消费者之间的互斥和同步关系,并提供了错误示例及正确实现,强调了临界条件判断的重要性。
摘要由CSDN通过智能技术生成

生产者与消费者模型:线程安全的队列(线程与线程之间对临界资源访问的一种编程思想)

功能:支持忙闲不均,解耦合,支持并发(线程安全)

场所:缓冲区。

角色:生产者,消费者

关系:三种关系 在生产者与消费者模型之中保证这么三种关系的实现,

生产者与生产者:互斥

生产者与消费者:同步与互斥

消费者与消费者:互斥

先来看一个错误的写法:

#include <iostream>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<queue>
using namespace std;
#define QUEUE_MAX 10

class BlockQueue
{
public:
    BlockQueue(int capacity = QUEUE_MAX):_capacity(capacity)
    {
        pthread_mutex_init(&_mutex, NULL);
        pthread_cond_init(&_full, NULL);
        pthread_cond_init(&_empty, NULL);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_full);
        pthread_cond_destroy(&_empty);
    }

    void push(int data)
    {
        pthread_mutex_lock(&_mutex);
        //用if是错误的
        if(_capacity == _list.size())
        {
            cout << "---------------full" << endl;
            pthread_cond_wait(&_full, &_mutex);
        }

        _list.push(data);
        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_empty);
    }

    void pop(int* data)
    {
        pthread_mutex_lock(&_mutex);
        if(_list.empty())
        {
            cout << "---------------empty" << endl;
            pthread_cond_wait(&_empty, &_mutex);
        }

        *data = _list.front();
        _list.pop();
        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_full);
    }
private:
    queue<int> _list;
    size_t _capacity;
    pthread_mutex_t _mutex;
    pthread_cond_t _full;
    pthread_cond_t _empty;
};


BlockQueue q;
int i = 1;

void* productor(void *arg)
{
    while(1)
    {
        cout << "productor_pthread:"<< arg  << " product:" << i << endl;
        q.push(i++);
    }
    return NULL;
}


void* consumer(void* arg)
{
    while(1)
    {
        int data;
        q.pop(&data);
        cout << "consumer_pthread:" << arg << " consume:" << data << endl;
    }
    return NULL;
}

int main()
{
    pthread_t tid1[4];
    pthread_t tid2[4];
    int ret;
    for(int i = 0; i < 4; ++i)
    {
        ret = pthread_create(&tid1[i], NULL, productor, (void*)i);
        if(0 != ret)
        {
            cout << "create pthread error" << endl;
            return -1;
        }
    }

    for(int i = 0; i < 4; ++i)
    {
        ret = pthread_create(&tid2[i], NULL, consumer, (void*)i);
        if(0 != ret)
        {
            cout << "create pthread error" << endl;
            return -1;
        }
    }

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

很明显,这个结果中,队列满了依然往里面添加任务。

原因:

同样当队列只有一个元素的时候,先来的消费者拿走了这个元素,后面来的线程就会越界访问导致代码奔溃。

正确的如下:

把临界条件的判断改为while。

#include <iostream>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<queue>
using namespace std;
#define QUEUE_MAX 10

class BlockQueue
{
public:
    BlockQueue(int capacity = QUEUE_MAX):_capacity(capacity)
    {
        pthread_mutex_init(&_mutex, NULL);
        pthread_cond_init(&_full, NULL);
        pthread_cond_init(&_empty, NULL);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_full);
        pthread_cond_destroy(&_empty);
    }

    void push(int data)
    {
        pthread_mutex_lock(&_mutex);
        //用if是错误的
        while(_capacity == _list.size())
        {
            cout << "---------------full" << endl;
            pthread_cond_wait(&_full, &_mutex);
        }

        _list.push(data);
        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_empty);
    }

    void pop(int* data)
    {
        pthread_mutex_lock(&_mutex);
        while(_list.empty())
        {
            cout << "---------------empty" << endl;
            pthread_cond_wait(&_empty, &_mutex);
        }

        *data = _list.front();
        _list.pop();
        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_full);
    }
private:
    queue<int> _list;
    size_t _capacity;
    pthread_mutex_t _mutex;
    pthread_cond_t _full;
    pthread_cond_t _empty;
};


BlockQueue q;
int i = 1;
void* productor(void *arg)
{
    while(1)
    {
        cout << "productor_pthread:"<< arg  << " product:" << i << endl;
        q.push(i++);
    }
    return NULL;
}


void* consumer(void* arg)
{
    while(1)
    {
        int data;
        q.pop(&data);
        cout << "consumer_pthread:" << arg << " consume:" << data << endl;
    }
    return NULL;
}

int main()
{
    pthread_t tid1[4];
    pthread_t tid2[4];
    int ret;
    for(int i = 0; i < 4; ++i)
    {
        ret = pthread_create(&tid1[i], NULL, productor, (void*)i);
        if(0 != ret)
        {
            cout << "create pthread error" << endl;
            return -1;
        }
    }

    for(int i = 0; i < 4; ++i)
    {
        ret = pthread_create(&tid2[i], NULL, consumer, (void*)i);
        if(0 != ret)
        {
            cout << "create pthread error" << endl;
            return -1;
        }
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值