阻塞队列的实现源码

1.BlockQueue.hpp

#pragma once
#include <iostream>
#include <pthread.h>
#include <mutex>
#include <queue>
#include <unistd.h>
//STL容器存在线程安全问题

const int gDefaultCap = 5;//最大容量capacity

template<class T>
class BlockQueue
{
private:
    bool isQueueEmpty()
    {
        return _bq.size() == 0;
    }
    bool isQueueFull()
    {
        return _bq.size() == _capacity;
    }
public:
    BlockQueue(int capacity = gDefaultCap):_capacity(capacity)
    {
        pthread_mutex_init(&_mtx, nullptr);
        pthread_cond_init(&_isFull, nullptr);
        pthread_cond_init(&_isEmpty, nullptr);
    }

    void Push(const T& in)
    {
        pthread_mutex_lock(&_mtx);
        // 1.先检测当前临界资源是否满足临界条件
        // pthread_cond_wait:第二个参数是一把锁,成功调用wait之后,传入的锁会自动释放
        // 从哪里阻塞挂起,就从哪里唤醒
        // 唤醒时pthread_cond_wait会自动获取锁
        while(isQueueFull()) pthread_cond_wait(&_isFull, &_mtx);
        // 2.访问临界资源
        _bq.push(in);
        // if(_bq.size() >= _capacity/2) pthread_cond_signal(&_isEmpty);
        pthread_cond_signal(&_isEmpty);
        pthread_mutex_unlock(&_mtx);
    }

    void Pop(T* out)
    {
        pthread_mutex_lock(&_mtx);
        while(isQueueEmpty()) pthread_cond_wait(&_isEmpty, &_mtx);

        *out = _bq.front();
        _bq.pop();
        pthread_cond_signal(&_isFull);//安全的
        pthread_mutex_unlock(&_mtx);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mtx);
        pthread_cond_destroy(&_isEmpty);
        pthread_cond_destroy(&_isEmpty);
    }
private:
    std::queue<T> _bq;       // 阻塞队列
    int _capacity;           // 容量上限
    pthread_mutex_t _mtx;    // 通过互斥锁保证队列安全
    pthread_cond_t _isEmpty; // 表示阻塞队列是否为空的条件
    pthread_cond_t _isFull;  // 表示阻塞队列是否为满的条件
};

2.ConProd.cc

#include "BlockQueue.hpp"

void* consumer(void *args)
{
    BlockQueue<int> *bqueue = (BlockQueue<int> *)args;
    while(true)
    {
        int a;
        bqueue->Pop(&a);
        std::cout << "消费一个数据:" << a << std::endl;
        sleep(1);
    }
    return nullptr;
}

void* productor(void *args)
{
    BlockQueue<int> *bqueue = (BlockQueue<int> *)args;
    int a = 1;
    while(true)
    {
        bqueue->Push(a);
        std::cout << "生产一个数据:" << a << std::endl;
        a++;
    }
    return nullptr;
}

int main()
{
    BlockQueue<int> *bqueue = new BlockQueue<int>();
    pthread_t c, p; // pthread_create最后一个参数为传入的数据
    pthread_create(&c, nullptr, consumer, bqueue);
    pthread_create(&p, nullptr, productor, bqueue);

    pthread_join(c, nullptr);
    pthread_join(p, nullptr);

    delete bqueue;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_63179783/article/details/129709493