C++ 安全队列
所谓的安全队列,就是封装一个加条件变量和互斥锁的一个队列类,以便在多线程访问该队列资源时是并行操作
1、多个线程从一个队列中读取数据,加互斥锁和条件变量
#ifndef SHAREDQUEUE_HPP #define SHAREDQUEUE_HPP #include<iostream> #include<memory> #include<queue> #include<mutex> #include<condition_variable> template <typename T> class SharedQueue { public: SharedQueue(); ~SharedQueue(); bool pop(std::unique_ptr<T>&& pData); void push(std::unique_ptr<T>&& item); int size(); bool empty(); public: T operator[] (int k) { return m_queue[k]; } private: std::deque<std::unique_ptr<T>> m_queue; std::mutex m_mutex; std::condition_variable m_cond; }; template <typename T> SharedQueue<T>::SharedQueue(){ } template <typename T> SharedQueue<T>::~SharedQueue(){ } template <typename T> bool SharedQueue<T>::pop(std::unique_ptr<T>&& pData) { std::unique_lock<std::mutex> mlock(m_mutex); if (m_queue.empty()) { return false; } pData = std::move(m_queue.front()); m_queue.pop_front(); return true; } template <typename T> void SharedQueue<T>::push(std::unique_ptr<T>&& item) { std::unique_lock<std::mutex> mlock(m_mutex); m_queue.push_back(std::move(item)); mlock.unlock(); m_cond.notify_all(); } template <typename T> int SharedQueue<T>::size() { std::unique_lock<std::mutex> mlock(m_mutex); int size = m_queue.size(); mlock.unlock(); return size; } template <typename T> bool SharedQueue<T>::empty() { std::unique_lock<std::mutex> mlock(m_mutex); return m_queue.empty(); } #endif
运行结果:
Thread idx : 0
pData : 0
pData : 1
pData : 2
pData : 3
pData : 4
pData : 5
pData : 6
pData : 7
pData : 8
pData : 9
Thread idx : 1
Thread idx : 2
Thread idx : 3
2、如果多线程安全队列是用在生产者和消费者场景中,即多个生产者(多个线程)往队列里写数据,多个消费者(多个线程)往队列中读数据
#ifndef SHAREDQUEUE_HPP #define SHAREDQUEUE_HPP #include<iostream> #include<memory> #include<queue> #include<mutex> #include<condition_variable> template <typename T> class SharedQueue { public: SharedQueue(); ~SharedQueue(); T& front(); T pop(); void pop_front(); void push_back(const T& item); void push_back(T&& item); void shut_down(); // bool pop(std::unique_ptr<T>&& pData); // void push(std::unique_ptr<T>&& item); int size(); bool empty(); bool is_shutdown(); public: T operator[] (int k) { return m_queue[k]; } private: std::deque<std::unique_ptr<T>> m_queue; std::mutex m_mutex; std::condition_variable m_cond; bool m_bShutDown = false; }; // #include"SharedQueue.hpp" template <typename T> SharedQueue<T>::SharedQueue(){ } template <typename T> SharedQueue<T>::~SharedQueue(){ } template <typename T> bool SharedQueue<T>::is_shutdown() { return m_bShutDown; } template <typename T> void SharedQueue<T>::shut_down() { std::unique_lock<std::mutex> mlock(m_mutex); m_queue.clear(); m_bShutDown = true; } template <typename T> T SharedQueue<T>::pop() { std::unique_lock<std::mutex> mlock(m_mutex); // if (m_queue.empty()) { // return false; // } m_cond.wait(mlock, [this](){return !this.m_queue.empty();}); T rc(std::move(m_queue.front())); m_queue.pop_front(); return rc; } template <typename T> T& SharedQueue<T>::front() { std::unique_lock<std::mutex> mlock(m_mutex); while(m_queue.empty()) { m_cond.wait(mlock); } return m_queue.front(); } template <typename T> void SharedQueue<T>::pop_front() { std::unique_lock<std::mutex> mlock(m_mutex); while(m_queue.empty()) { m_cond.wait(mlock); } m_queue.pop_front(); } template <typename T> void SharedQueue<T>::push_back(const T& item) { std::unique_lock<std::mutex> mlock(m_mutex); m_queue.push_back(item); mlock.unlock(); m_cond.notify_one(); } template <typename T> void SharedQueue<T>::push_back(T&& item) { std::unique_lock<std::mutex> mlock(m_mutex); m_queue.push_back(std::move(item)); mlock.unlock(); m_cond.notify_one(); } template <typename T> int SharedQueue<T>::size() { std::unique_lock<std::mutex> mlock(m_mutex); int size = m_queue.size(); mlock.unlock(); return size; } template <typename T> bool SharedQueue<T>::empty() { std::unique_lock<std::mutex> mlock(m_mutex); bool is_empty = m_queue.empty(); mlock.unlock(); return is_empty; } #endif