C++并发编程:构建线程安全队列(第二部分:细粒度锁)
C++并发编程:构建线程安全队列(第二部分:细粒度锁)
1. 引言
在多线程环境下,为了保证数据的一致性和正确性,需要使用同步原语来对共享数据的访问进行互斥和同步。std::queue
作为一种先进先出(FIFO)的数据结构,它本身并不是线程安全的,同时访问它可能导致数据竞争和不一致的问题。
所以在多线程环境下,我们需要构建一个线程安全的队列,使其可以安全地被多个线程同时访问,而不会出现数据竞争。这里我们使用C++11中的一些新特性如std::shared_ptr
、std::unique_ptr
、std::mutex
、std::condition_variable
等来实现一个线程安全队列。
2. 设计要点
线程安全队列的关键设计要点包括:
- 使用互斥量保护队列的头尾指针,使多线程不能同时修改队列结构
- 使用条件变量实现线程之间的通知和等待,避免忙等待(busy waiting)
- 提供多种不同的访问接口如阻塞、非阻塞、等待获取等,增强队列的实用性
- 使用
std::shared_ptr
、std::unique_ptr
等智能指针管理内存,避免手动new/delete带来的问题 - 尽量减少锁的粒度,例如头尾指针使用不同的锁,以提高并发性
下面我们来看一下这个线程安全队列的具体设计和实现。
3. 队列的节点结构
队列节点node
使用一个std::shared_ptr
保存数据,和一个std::unique_ptr
指向下一节点:
struct node
{std::shared_ptr<T> data;std::unique_ptr<node> next;
};
使用shared_ptr
而不是原始指针管理数据,可以自动释放内存,避免泄漏。unique_ptr
则保证节点间的引用关系唯一,方便传递所有权。
4. 队列结构
队列结构包含头尾指针、互斥量和条件变量:
std::mutex head_mutex;
std::unique_ptr<node> head;std::mutex tail_mutex;
node* tail;std::condition_variable data_cond;
头指针使用unique_ptr
且初始化为一个哑节点。尾指针使用原始指针,初始化指向哑节点。
头尾指针分别使用head_mutex
和tail_mutex
保护,以减小锁的粒度,不同指针可以并发修改。
条件变量data_cond
用于在队列为空时等待,并在有数据可获取时发出通知。
5. 主要接口
队列主要提供下面一些接口:
5.1 非阻塞获取
try_pop
尝试非阻塞地弹出队头元素,如果队列为空则直接返回:
std::shared_ptr<T> try_pop()
{std::lock_guard<std::mutex> head_lock(head_mutex);if (head.get() == get_tail()) {return {}; }return std::move(head->data);
}
仅对头指针上锁,执行常数时间操作,可并发访问。
5.2 阻塞获取
wait_and_pop
会在队列为空时等待,直到有元素入队后唤醒线程并返回数据:
std::shared_ptr<T> wait_and_pop()
{std::unique_lock<std::mutex> head_lock(wait_for_data());return std::move(head->data);
}std::unique_lock<std::mutex> wait_for_data()
{std::unique_lock<std::mutex>
相关文章:

C++并发编程:构建线程安全队列(第二部分:细粒度锁)
C++并发编程:构建线程安全队列(第二部分:细粒度锁) 1. 引言 在多线程环境下,为了保证数据的一致性和正确性,需要使用同步原语来对共享数据的访问进行互斥和同步。std::queue作为一种先进先出(FIFO)的数据结构,它本身并不是线程安全的,同时访问它可能导致数据竞争和不一致的问…...

浅述C++内存管理——new与malloc的不同
前言 C相对于其他语言有一个重要的特点就是对于内存的管理,相比于C语言,C提供了新的关键字new来代替malloc的功能,其中有何不同,请看下文。 一、内存的构成 在我们日常编程过程中最常接触到的就是以下四个分区 以下将分别给出例…...

语言基础篇11——函数、函数参数类型、装饰器、生成器
函数 基本结构 def func_name(value):print(f"Hello {value}")return 0func_name("World")函数参数 参数默认值和五种参数类型 https://docs.python.org/3/glossary.html#term-parameter 参数默认值 带默认值的参数必须在参数列表右边 def func_nam…...

linux jar包class热部署 工具 arthas安装及使用
在不改变类、方法 的前提下,在方法中对业务逻辑做处理 或 打日志等情况下使用。 建议线上日志调试时使用: arthas安装 1. 下载文件 arthas-packaging-3.7.1-bin.zip https://arthas.aliyun.com 2. 服务器安装arthas 2.1 服务器指定目录下创建目录 c…...

Android studio 调整jar包顺序
第一步:编译jar包,放入lib路径下:如: 第二步:app 目录下build.gradle 中添加 compileOnly files(libs/classes.jar) 第三步:project目录下build.gradle 中添加 allprojects {gradle.projectsEvaluated {t…...

用Qt写的机器视觉绘图工具
一个用QtGraphicsView写的机器视觉绘图工具,支持直线查找,圆拟合,卡尺工具,圆环查找等。底部GraphicsScene可以实时显示相机图像,工具获取图像后通过算法处理图像。 Project是基于Qt的例程项目qdraw改的。...

Spring Boot 打包,将依赖全部打进去
一、背景 spring boot 2.4.4 项目,打包,将依赖全部打进去 二、在pom.xml中引入插件 在项目的 pom.xml 文件中,添加 Maven 插件 spring-boot-maven-plugin,示例如下: <build><plugins><!-- ...其他插件…...

SpringCloud入门实战(十五)分布式事务框架Seata简介
📝 学技术、更要掌握学习的方法,一起学习,让进步发生 👩🏻 作者:一只IT攻城狮 ,关注我,不迷路 。 💐学习建议:1、养成习惯,学习java的任何一个技术…...

MySQL数据库 主从复制与读写分离
读写分离是什么 读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。 为什么要进行读写分离 因…...

Qt day2
目录 1.多态,虚函数,纯虚函数 1.多态性(Polymorphism): 2.虚函数(Virtual Function): 3.纯虚函数(Pure Virtual Function): 将引用作为函数参…...

JavaScript - 好玩的打字动画
效果预览: 🚀HTML版本 <!DOCTYPE html> <html> <head><title>打字动画示例</title><style>.typewriter {color: #000;overflow: hidden; /* 隐藏溢出的文本 */white-space: nowrap; /* 不换行 */border-right: .…...

rpm打包
文章目录 rpm打包 1. rpm打包步骤0)准备工作:安装打包工具rpm-build和rpmdevtools(1)在线安装(2)离线安装 1)创建初始化目录2)准备打包内容3)编写打包脚本 spec文件4&…...

匠心新品:大彩科技超薄7寸WIFI线控器发布,热泵、温控器、智能家电首选!
一、产品介绍 此次发布一款7寸高清全新外壳产品,让HMI人机界面家族再添一新成员。该产品相比其他外壳有以下5个大改动: 1 表面玻璃盖板使用2.5D立体结构; 2 液晶盖板采用一体黑设计,且液晶屏与触摸板是全贴合结构; …...

华为云云服务器评测|使用云耀云服务器L实例部署Portainer工具
华为云云服务器评测|使用云耀云服务器L实例部署Portainer工具 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点1.3 云耀云服务器L实例使用场景 二、本次实践介绍2.1 本次实践简介2.2 Portainer简介 三、购买云耀云服务器L实例3.1 登录…...

C++并发编程:构建线程安全队列(第一部分:粗粒度锁)
C并发编程:构建线程安全队列(第一部分:粗粒度锁) 引言 在多线程编程中,线程之间的数据共享和通信是一个非常重要的问题。在这篇博客中,我们将讨论如何用C实现一个基础但非常实用的线程安全队列。这个队列…...

C++设计模式-更新中
单例模式 这个类实现了单例模式。单例模式是一种设计模式,旨在确保一个类只有一个实例,并提供一个全局访问点来获取该实例。 在 ConnectionManager 类中,它通过以下方式实现了单例模式: 构造函数 ConnectionManager() 被声明为…...

Hydra工具的使用
目录 Hydra初识 Hydra使用 hydra破解mysql 前言 不固定用户名密码爆破 hydra破解ssh 以用户名为密码登录 hydra破解rdp 将爆破密码的结果输出到文件中 Hydra初识 前言: hydra是一款开源的暴力破解工具,支持多种服务破解原理:使用户…...

Pytorch学习:卷积神经网络—nn.Conv2d、nn.MaxPool2d、nn.ReLU、nn.Linear和nn.Dropout
文章目录 1. torch.nn.Conv2d2. torch.nn.MaxPool2d3. torch.nn.ReLU4. torch.nn.Linear5. torch.nn.Dropout 卷积神经网络详解:csdn链接 其中包括对卷积操作中卷积核的计算、填充、步幅以及最大值池化的操作。 1. torch.nn.Conv2d 对由多个输入平面组成的输入信号…...

水果库存系统(SSM+Thymeleaf版)
不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。 文章目录 一、前言二、系统架构与需求分析1、技术栈1.1 后端1.2 前端 2、需求分析 三、设计…...

如何在VueJS应用程序中设置Toast通知
通知是开发者提升应用程序互动性和改善用户体验的强大工具。通过利用通知,开发者可以在用户与应用程序互动的同时,有效地向用户传达重要事件。 通知在应用程序中起着至关重要的作用,可以及时通知用户有关各种操作和事件的信息。它们可以用于通…...

css让元素保持等比例宽高
使用新属性 aspect-ratio: 16/9; 代码示例 <style>div {width: 60%;/* 等比例宽高 */aspect-ratio: 16/9;background-color: red;margin: auto;}</style> </head><body><div></div> </body>示例 aspect-ratio兼容性...

骨传导和入耳式哪个危害大一点?入耳式和骨传导哪种好?
骨传导和入耳式这两种耳机虽然都存在一定的危害,但是入耳式耳机对人体的危害要更大一点。 入耳式耳机直接塞进耳朵这种佩戴方式,会阻塞外部声音的进入,长时间使用可能会导致耳道感染,还可能对听力造成损伤,而骨传导耳…...

介绍OpenCV
OpenCV是一个开源计算机视觉库,可用于各种任务,如物体识别、人脸识别、运动跟踪、图像处理和视频处理等。它最初由英特尔公司开发,目前由跨学科开发人员社区维护和支持。OpenCV可以在多个平台上运行,包括Windows、Linux、Android和…...

Android中的view绘制流程,简单理解
简单理解 Android中的View类代表用户界面中基本的构建块。一个View在屏幕中占据一个矩形区域、并且负责绘制和事件处理。View是所有widgets的基础类,widgets是我们通常用于创建和用户交互的组件,比如按钮、文本输入框等等。子类ViewGroup是所有布局&…...

商城开发:店铺管理系统应具备哪些功能?
电子商务的迅猛发展,越来越多的企业选择在线商城作为业务拓展的重要渠道。而要实现一个成功的在线商城,一个强大而高效的店铺管理系统是不可或缺的。店铺管理系统作为商城的核心管理工具,应具备一系列功能,以提供卓越的用户体验和…...

小白学go基础04-命名惯例对标识符进行命名
计算机科学中只有两件难事:缓存失效和命名。 命名是编程语言的要求,但是好的命名却是为了提高程序的可读性和可维护性。好的命名是什么样子的呢?Go语言的贡献者和布道师Dave Cheney给出了一个说法:“一个好笑话,如果你…...

使用iCloud和Shortcuts实现跨设备同步与自动化数据采集
在如今的数字时代,跨设备同步和自动化数据采集对于提高工作效率和便利性至关重要。苹果的iCloud和Shortcuts App为我们提供了强大的工具,可以实现跨设备同步和自动化数据采集的功能。本文将详细介绍如何利用iCloud和Shortcuts App实现这些功能࿰…...

Spring框架-基于STOMP使用Websocket
文章目录 前言一、范例演示1.注解方式2.XML方式二、可能出现错误错误: WebSocket代理中断错误: 缺少EventExecutor类错误: 缺少Publisher类错误: 缺少Scheduler类错误: WebSocket调用失败总结前言 Spring框架提供了多种WebSock消息机制,不仅包含了模拟SockJS,还提供了基…...

kafka-- 安装kafka manager及简单使用
一 、安装kafka manager 管控台: # 安装kafka manager 管控台: ## 上传 cd /usr/local/software ## 解压 unzip kafka-manager-2.0.0.2.zip -d /usr/local/ cd /usr/local/kafka-manager-2.0.0.2/conf vim /usr/local/kafka-manager-2.0.0.2/conf/appl…...

深圳-海岸城购物中心数据分析
做数据分析的时候,如果要对商场进行分析,可以从这些数据纬度进行分析,如下图所示: 截图来源于数位观察:https://www.swguancha.com/...