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;
}
C++ 线程安全的队列的更多相关文章
- (转)java自带线程池和队列详细讲解 - CSDN过天的专栏
一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后加入了java.util ...
- java自带线程池和队列详细讲解
Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后 ...
- 深入浅出Win32多线程设计之MFC的多线程-线程与消息队列(经典)
1.创建和终止线程 在MFC程序中创建一个线程,宜调用AfxBeginThread函数.该函数因参数不同而具有两种重载版本,分别对应工作者线程和用户接口(UI)线程. 工作者线程 CWinThread ...
- Java线程:堵塞队列与堵塞栈
一.堵塞队列 Java定义了堵塞队列的接口java.util.concurrent.BlockingQueue,堵塞队列是一个指定长度的队列,当试图向队列中添加元素而队列已满,或者是想从队列移出元素而 ...
- python端口扫描用多线程+线程安全的队列+Thread类实现
用线程安全的队列Queue实现扫描端口数据存储 用多线程扫描端口 用Thread类实现程序组织 #coding:utf-8 import sys import socket import sys im ...
- c/c++ 多线程 利用条件变量实现线程安全的队列
多线程 利用条件变量实现线程安全的队列 背景:标准STL库的队列queue是线程不安全的. 利用条件变量(Condition variable)简单实现一个线程安全的队列. 代码: #include ...
- 线程中的队列(queue)
队列的类型和常用方法 队列是一种数据结构,它类似于列表.但列表是线程不安全的,而队列是线程安全的. python的queue(python3,python2为Queue)提供了3种队列: Queue: ...
- java线程自带队列的使用以及线程阻塞
java线程,设置队列的大小实现队列阻塞 public class QueueThreads { private static int nThreads = 4;//Runtime.getRuntim ...
- Java自带线程池和队列详解
Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后 ...
- java自带线程池和队列详细讲解<转>
Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后 ...
随机推荐
- P1481魔族密码 题解(字典树)
魔族密码 题目背景 风之子刚走进他的考场,就-- 花花:当当当当~~偶是魅力女皇--花花!!^^(华丽出场,礼炮,鲜花) 风之子:我呕--(杀死人的眼神)快说题目!否则---_-### 题目描述 花花 ...
- windows 程序启动后挂到后台
开发中遇到一个问题,程序启动后,并没有出现在前台,而是自动挂到后台,程序处于卡死状态,基本任何模块都没加载进来. 后面排查发现跟一个功能的第三方 dll 有关系,在那个 dll 加载时导致程序卡死,因 ...
- 项目实战:Qt+Android模拟操作器(模拟操作app,打开,点击,输入,获取验证码等等)
若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109313803各位读者,知识无穷而人力有穷,要 ...
- 【Azure Redis 缓存】Redis连接无法建立问题的排查(注:Azure Redis集成在VNET中)
问题描述 在Azure App Service中部署的应用,需要连接到Redis中,目标Redis已经集成了虚拟网络(VNET)并且在Redis的网络防火墙中已经添加App Service的出站IP地 ...
- ffmpeg 使用记录
这周周末尝试把我硬盘上面的视频文件压缩了一下,但是效果并不理想.其中主要有两个原因, 视频本来就是h264的编码,再重新编码也没啥用,因为限制大小的主要是码率 ffmpeg GPU加速版的h265编码 ...
- Java 开发人员调度软件项目 (java基础编程总结项目)+javaBean+测试代码+数组知识+数据结构+继承+多态+封装+自定义异常,异常处理+构造器知识+重载+重写+接口+实现接口+关键字使用(static +equalsIgnoreCase+fianl+instanceof判断类型)+向下转型与向上转型
/** * * @Description Java 开发人员调度软件项目 (java基础编程总结项目) * +javaBean+测试代码+数组知识+数据结构+继承+多态+封装+自定义异常,异常处理 * ...
- 2、dubbo原理
图例说明: 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口. 图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖 ...
- zookeeper源码(10)node增删改查及监听
本文将从leader处理器入手,详细分析node的增删改查流程及监听器原理. 回顾数据读写流程 leader ZookeeperServer.processPacket封装Request并提交给业务处 ...
- 图片裁剪插件 vue-cropper [vue插件推荐]
一个优雅的图片裁剪插件 https://www.npmjs.com/package/vue-cropper http://github.xyxiao.cn/vue-cropper/example/
- 基于DSP的设备振动信号的采集和处理模块研发总结
前记 在能源领域,由于很多地方都是无人值守,设备故障检测是一个必须面对的问题.笔者通过最近几个行业案例了解到,由于很多设备发生故障时候会产生特定频谱的声音,所以该行业对振动监测的需求特别强烈,由于涉 ...