C++线程安全的队列你了解嘛

 更新时间:2022年03月10日 10:31:46   作者:吃米饭  
这篇文章主要为大家详细介绍了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::move(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; ++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;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容! 

相关文章

  • 使用C++一步步实现俄罗斯方块后续

    使用C++一步步实现俄罗斯方块后续

    本文主要给大家分享的是作者在使用C++制作俄罗斯方块小游戏的时候所需要的常用的函数,有需要的小伙伴可以借鉴下,希望大家能够喜欢。
    2017-12-12
  • 利用C/C++二进制读写png文件的方法示例

    利用C/C++二进制读写png文件的方法示例

    最近在做项目的时候遇到了这个问题,所以想着总结下,方法自己和有需要的朋友,下面这篇文章主要介绍了利用C/C++二进制读写png文件的方法,需要的朋友可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • C语言实现顺序表的基本操作的示例详解

    C语言实现顺序表的基本操作的示例详解

    顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。本文将通过示例为大家讲解一下顺序表的基本操作,需要的可以参考一下
    2022-11-11
  • C语言 文件操作解析详解及实例代码

    C语言 文件操作解析详解及实例代码

    这篇文章主要介绍了C语言 文件操作解析详解及实例代码的相关资料,需要的朋友可以参考下
    2016-11-11
  • C++实现二叉树基本操作详解

    C++实现二叉树基本操作详解

    这篇文章主要为大家详细介绍了C++实现二叉树基本操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • C++实现LeetCode(38.计数和读法)

    C++实现LeetCode(38.计数和读法)

    这篇文章主要介绍了C++实现LeetCode(38.计数和读法),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言操作符基础知识详解

    C语言操作符基础知识详解

    这篇文章主要以图文结合的方式为大家详细介绍了C语言位运算基础知识,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-10-10
  • 深入理解大数与高精度数的处理问题

    深入理解大数与高精度数的处理问题

    本篇文章是对大数与高精度数的处理进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C++示例分析内联函数与引用变量及函数重载的使用

    C++示例分析内联函数与引用变量及函数重载的使用

    为了消除函数调用的时空开销,C++ 提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开。这种在函数调用处直接嵌入函数体的函数称为内联函数(Inline Function),又称内嵌函数或者内置函数
    2022-08-08
  • C语言宏函数container of()简介

    C语言宏函数container of()简介

    这篇文章介绍了C语言宏函数container of(),对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12

最新评论