• C++ 线程安全的队列


    在这里插入图片描述

    无界队列

    #include<queue>
    #include<mutex>
    #include<condition_variable>
    #include<optional>
    #include<cassert>
    #include<thread>
    
    template<typename T,typename Container = std::queue<T>>
    class Queue	//无界队列
    {
    public:
    	Queue() = default;
    	~Queue() = default;
    
    	//禁止拷贝和移动,编译器会自动delete
    	/*Queue(const Queue&) = delete;
    	Queue(Queue&&) = delete;
    	Queue& operator=(const Queue&) = delete;
    	Queue& operator=(Queue&&) = delete;*/
    
    
    	void push(const T& val)
    	{
    		emplace(val);
    	}
    
    	void push(T&& val)
    	{
    		emplace(std::move(val));
    	}
    	
    	template<typename...Args>
    	void emplace(Args&&...args)
    	{
    		std::lock_guard lk{ mtx_ };
    		q_.push(std::forward<Args>(args)...);
    		cv_.notify_one();
    	}
    
    	T pop()//阻塞
    	{
    		std::unique_lock lk{ mtx_ };
    		cv_.wait(lk, [this] {return !q_.empty(); });//如果队列不为空就继续执行,否则阻塞
    		assert(!q_.empty());
    		T ret{ std::move_if_noexcept(q_.front()) };
    		q_.pop();
    		return ret;
    	}
    
    
    	std::optional<T> try_pop()//非阻塞
    	{
    		std::unique_lock lk{ mtx_ };
    		if (q_.empty())return {};
    		std::optional<T> ret{ std::move_if_noexcept(q_.front()) };
    		q_.pop();
    		return ret;
    	}
    	bool empty()const
    	{
    		std::lock_guard lk{ mtx_ };
    		return q_.empty();
    	}
    private:
    	Container q_;
    	mutable std::mutex mtx_;
    	std::condition_variable cv_;
    };
    
    #include<iostream>
    int main()
    {
    	Queue<int>q;
    	std::thread t1(
    		[&] {
    			for (int i = 0; i < 100; ++i)
    			{
    				q.push(i);
    			}
    		});
    
    	std::thread t2(
    		[&] {
    			for (int i = 0; i < 100; ++i)
    			{
    				//std::cout<<q.pop()<<" ";
    				if (auto ret = q.try_pop())
    				{
    					std::cout << *ret<<" ";
    				}
    			}
    		});
    	t1.join();
    	t2.join();
    	return 0;
    }
    

    有界队列

    #include<mutex>
    #include<condition_variable>
    #include<boost/circular_buffer.hpp>
    #include<optional>
    
    template<typename T>
    class Queue
    {
    public:
    	Queue(size_t capacity) :q_{ capacity } {}
    
    	template<typename T>
    	void push(T&& val)//阻塞
    	{
    		std::unique_lock lk{ mtx_ };
    		not_full_.wait(lk, [this] {return !q_.full(); });
    		assert(!q_.full());
    		q_.push_back(std::forward<T>(val));
    		not_empty_.notify_one();
    	}
    
    	template<typename T>
    	bool try_push(T&& val)//非阻塞
    	{
    		std::lock_guard lk{ mtx_ };
    		if (q_.full())return false;
    		q_.push_back(std::forward<T>(val));
    		not_empty_.notify_one();
    		return true;
    	}
    
    	T pop()//阻塞
    	{
    		std::unique_lock lk{ mtx_ };
    		not_empty_.wait(lk, [this] {return !q_.empty(); });
    		asert(!q_.empty());
    		T ret{ std::move_if_noexcept(q_.front()) };
    		q_.pop_front();
    		not_full_.notify_one();
    		return ret;
    
    	}
    	std::optional<T> try_pop()//非阻塞
    	{
    		std::lock_guard lk{ mtx_ };
    		if (q_.empty())return {};
    		std::optional<T> ret{ std::move_if_noexcept(q_.front()) };
    		q_.pop_front();
    		not_full_.notify_one();
    		return ret;
    	}
    
    private:
    	boost::circular_buffer<T>q_;
    	std::mutex mtx_;
    	std::condition_variable not_full_;
    	std::condition_variable not_empty_;
    };
    
    #include<iostream>
    int main()
    {
    	Queue<int>q{10};
    	std::thread t1(
    		[&] {
    			for (int i = 0; i < 100;)
    			{
    				if (q.try_push(i))
    				{
    					i++;
    				}
    			}
    		});
    
    	std::thread t2(
    		[&] {
    			for (int i = 0; i < 100;)
    			{
    				//std::cout<<q.pop()<<" ";
    				if (auto ret = q.try_pop())
    				{
    					std::cout << *ret << " ";
    					++i;
    				}
    			}
    		});
    	t1.join();
    	t2.join();
    	return 0;
    }
    
  • 相关阅读:
    团队工作第四次推进之——软件设计规格说明书
    失物找寻APP软件需求规格说明书——第三次团队作业
    你还在为校园内丢失东西无处可寻而发愁吗?速戳进来
    十分有趣却有些遗憾的结对编程——两位女程序员的挣扎
    结对编程初涉猎——结对伙伴的代码复审
    个人实战演练全过程——No.1 最大连续子数组求和
    小白出品 单元测试相关——入门级说明书
    写着写着停不下来的普通女程序员的总结
    vs2010 和vs2012的区别 副标题--Loaded事件走两次
    汽车防撞软件引发的一套软件系统思路
  • 原文地址:https://www.cnblogs.com/chengmf/p/15983140.html
Copyright © 2020-2023  润新知