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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2019-10-20 02-线性结构3 Reversing Linked List (25 分)