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/C++实现字符串模糊匹配

    本文分别给大家介绍了2个C++在Linux平台和windows平台下实现字符串模糊匹配的方法,基本的核心思想都是一样的,均是使用fnmatch函数,有需要的小伙伴可以参考下。
    2016-04-04
  • C语言实现选票统计

    C语言实现选票统计

    这篇文章主要为大家详细介绍了C语言实现选票统计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • 基于C语言实现简单的扫雷小游戏

    基于C语言实现简单的扫雷小游戏

    这篇文章主要为大家详细介绍了基于C语言实现简单的扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Qt5升级到Qt6分步迁移教程小结

    Qt5升级到Qt6分步迁移教程小结

    Qt框架的一个新的长期支持版本6.5最近发布,本文主要介绍了Qt5升级到Qt6分步迁移教程小结,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • 深入聊聊C语言中的Const关键字

    深入聊聊C语言中的Const关键字

    关键字const用来定义只读变量,被const定义的变量它的值是不允许改变的,即不允许给它重新赋值,即使是赋相同的值也不可以,下面这篇文章主要给大家介绍了关于C语言中Const关键字的相关资料,需要的朋友可以参考下
    2022-02-02
  • C语言数组a和&a的区别讲解

    C语言数组a和&a的区别讲解

    今天小编就为大家分享一篇关于C语言数组a和&a的区别讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • C++ 内存分配处理函数set_new_handler的使用

    C++ 内存分配处理函数set_new_handler的使用

    这篇文章主要介绍了C++ 内存分配处理函数set_new_handler的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • C++不使用变量求字符串长度strlen函数的实现方法

    C++不使用变量求字符串长度strlen函数的实现方法

    这篇文章主要介绍了C++不使用变量求字符串长度strlen函数的实现方法,实例分析了strlen函数的实现原理与不使用变量求字符串长度的实现技巧,需要的朋友可以参考下
    2015-06-06
  • C++中拷贝构造函数的使用

    C++中拷贝构造函数的使用

    大家好,本篇文章主要讲的是C++中拷贝构造函数的使用,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • C++基础入门教程(五):new和delete

    C++基础入门教程(五):new和delete

    这篇文章主要介绍了C++基础入门教程(五):new和delete,本文讲解了动态分配内存、new和delete的配对、new、delete与reatin、release的关系、动态数组等内容,需要的朋友可以参考下
    2014-11-11

最新评论