实现一个多线程下的安区缓冲区

18 阅读1分钟

需求:

  • 支持push:缓冲区满了应当阻塞等待
  • 支持pop:移除缓冲区元素
  • 支持size:获取缓冲区大小
  • 支持多个生产者和消费者同时访问,并保证线程安全
#include <queue>
#include <conditonal_variable>
#include <thread>
#include <mutex>


template <typename T>
class SaveBufer {
    private:
        std::queue<T> m_queue;
        std::conditonal_variable consumer_con;
        std::conditonal_variable producer_con;
        int m_size;
        std::mutex m_mux; // !
   public:
       explict SaveBufer(int size) {
           m_size = size;
       }
       void push(T &item);
       T& pop();
       int size(){
           std::lock_guard<std::mutex> lock(m_mux);//!!
           return m_queue.size();
       }
};

template <typename T>
void SaveBufer<T>::push(T& item)//!
{
    std::unique_lock<std::mutex> lock(m_mux);//!!
    producer_con.wait(lock,[this](){
        return m_queue.size() < m_size;
    });
    m_queue.push(item);
    consumer_con.notify_all();//!!
}

template <typename T>
T& SaveBufer<T>::pop()
{
    std::unique_lock<std::mutex> lock(m_mux);//!!
    consumer_con.wait(lock,[this](){
        return m_queue.size() > 0;
    });
    T& item = m_queue.front();
    m_queue.pop();
    producer_con.notify_all();
    return item;
}

void consumer(int id,std::shared_ptr<SaveBufer<int>> buf)//!
{
    while(true) {
        buf.pop();
        std::cout << "id:" << id << ",consume\n";
        std::this_thread::sleep_for(std::chrono::second(1));
    }
}

void produce(int id,std::shared_ptr<SaveBufer<int>> buf)
{
    while(true) {
        int a = 100;
        buf.push(a);
        std::cout << "id:" << id << ",produce\n";
        std::this_thread::sleep_for(std::chrono::second(1));
    }
}

int main()
{
    std::shared_ptr<SaveBuffer<int>> buf = std::make_shared<SaveBuffer<int>>(10);
    std::thread t1(consumer,1,std::ref(buf));//用ref!!
    std::thread t2(produce,2,std::ref(buf));
    t1.join();
    t2.join();
}