C++ 并发专题 - 无锁数据结构(队列)

一:概述:

        当我们在并发程序中使用队列时,通常会使用锁来同步推入(push)和弹出(pop)操作。我们会在执行推入或弹出操作之前加锁,并在函数结束之前解锁。然而,锁的使用会带来一些开销,包括创建和获取锁的成本。因此,如果我们能够完全避免使用锁,并仍然支持并发操作,那将是非常理想的。对于许多数据结构,如链表、栈和队列,我们可以借助原子操作中的比较并交换(CAS)来实现同步、无锁版本。在 C++ 中,它被称为 std::atomic<T>::compare_exchange_weak

二:什么是CAS

        CAS 最初是 IBM 在 1973 年引入的 CPU 指令。请记住,只有原始的 CPU 指令才能真正做到原子操作。我们要感谢硬件工程师们给我们带来了 CAS,因为它确实是一个非常棒且有用的指令。

        std::atomic<T>::compare_exchange_weak 会将 std::atomic<T> 的当前值与预期值进行比较,如果相等,则将 std::atomic<T> 的值替换为期望的目标值。以下是一个简化的 C++ 代码示例,展示了它的工作原理:

template <typename T>
bool compare_exchange_weak_example(std::atomic<T>& atomic_var, T& expected, T desired) {// 进行比较交换bool success = atomic_var.compare_exchange_weak(expected, desired);// 如果交换成功,返回 true;否则,返回 falsereturn success;
}

三:实现

template<typename T>
class lock_free_queue
{
private:// 节点结构,队列中的每个元素都封装在一个节点中struct node{std::shared_ptr<T> data;  // 存储数据,使用 shared_ptr 自动管理内存std::atomic<node*> next;  // 原子指针,指向下一个节点node(T const& data_) :data(std::make_shared<T>(data_)) {}  // 构造函数,初始化节点数据};std::atomic<node*> head;  // 队列头部的原子指针std::atomic<node*> tail;  // 队列尾部的原子指针public:// 向队列尾部添加一个元素void push(T const& data){// 创建一个新的节点并初始化数据std::atomic<node*> const new_node = new node(data);// 获取当前尾节点的指针node* old_tail = tail.load();// 尝试更新尾节点的 next 指针,直到成功while (!old_tail->next.compare_exchange_weak(nullptr, new_node)) {// 如果尾节点的 next 指针不是 nullptr,表示其他线程已经插入了节点// 需要重新加载尾节点并重试old_tail = tail.load();}// 尝试将尾节点更新为新的节点tail.compare_exchange_weak(old_tail, new_node);}// 从队列头部弹出一个元素std::shared_ptr<T> pop(){// 获取当前头节点的指针node* old_head = head.load();// 尝试更新队列的头节点,直到成功while (old_head &&!head.compare_exchange_weak(old_head, old_head->next)) {// 如果头节点的 next 指针不为空,表示其他线程已经移除了节点// 需要重新加载头节点并重试old_head = head.load();}// 如果成功获取到头节点,则返回数据;否则返回空的 shared_ptr,表示队列为空return old_head ? old_head->data : std::shared_ptr<T>();}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/467562.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue用jenkins 打包项目项目关闭eslint检查

问题描述&#xff1a;创建vue脚手架项目后&#xff0c;使用jenkins 打包项目&#xff0c;出现如下图所示错误&#xff0c;显示错误来源于eslint检测。 解决方法&#xff1a;在根目录下找到vue.config.js文件&#xff0c;添加lintOnSave: false以关闭eslint检测&#xff0c;项目…

基于Spring Boot的美术馆管理系统的设计与实现,LW+源码+讲解

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统美术馆管理系统信息管理难度大&#xff0c;容错率低&…

战略共赢 软硬兼备|云途半导体与知从科技达成战略合作

2024年11月5日&#xff0c;江苏云途半导体有限公司&#xff08;以下简称“云途”或“云途半导体”&#xff09;与上海知从科技有限公司&#xff08;以下简称“知从科技”&#xff09;达成战略合作&#xff0c;共同推动智能汽车领域高端汽车电子应用的开发。 云途半导体与知从科…

【TMM2024】Frequency-Guided Spatial Adaptation for Camouflaged Object Detection

论文链接&#xff1a;https://arxiv.org/abs/2409.12421 这个论文研究 Camouflaged Object Detection &#xff08;COD&#xff09;问题&#xff0c;作者认为&#xff0c;使用 pretrained foundation model 可以改进COD的准确率&#xff0c;但是当前的 adaptor 大多学习空间特…

前端环境配置

对于换公司的小伙伴来讲&#xff0c;重新安装环境&#xff0c;百度或许稍微有点麻烦&#xff0c;本文章让你无脑式直接操作&#xff0c;保证环境畅通无阻。 1.安装nvm-setup 该插件是一款管理nodeJs的包&#xff0c;无需你单独下载nodeJs去安装&#xff0c;只需要下载安装此…

window中借助nginx配置vite+vue项目的反向代理步骤

在官网下载好nginx的安装包后&#xff0c;解压后 CMD打开 start nginx 是启动命令 nginx -s stop 停止服务 nginx -s reload 如果重写了nginx.conf文件&#xff0c;要执行这条命令 正常情况下 成功启动和成功停止服务长这样 错误情况&解决 如果nginx -s stop失败 ngi…

论文阅读:基于语义分割的非结构化田间道路场景识别

论文地址&#xff1a;DOI: 10.11975/j.issn.1002-6819.2021.22.017 概要 环境信息感知是智能农业装备系统自主导航作业的关键技术之一。农业田间道路复杂多变&#xff0c;快速准确地识别可通行区域&#xff0c;辨析障碍物类别&#xff0c;可为农业装备系统高效安全地进行路径规…

【Ant Design Pro】如何实现组件的状态保存umi-plugin-keep-alive插件的使用

都知道vuejs里面帮我们实现了一个内置的keep-alive组件&#xff0c;给我们缓存一些组件的状态带来了很大的便利。但是在react中没有自带的实现&#xff0c;可以借助社区的插件umi-plugin-keep-alive来实现这个功能。 实现效果对比 未使用插件&#xff0c;可以看到我们在页面跳…

Amesim中PID控制元件

PID 控制原理 PID 即比例&#xff08;Proportional&#xff09;、积分&#xff08;Integral&#xff09;、微分&#xff08;Derivative&#xff09;控制。比例环节根据偏差的大小成比例地对系统进行调节&#xff0c;偏差越大&#xff0c;调节作用越强。积分环节用于消除系统的…

SpringBoot框架:共享汽车行业的技术革新

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了共享汽车管理系统的开发全过程。通过分析共享汽车管理系统管理的不足&#xff0c;创建了一个计算机管理共享汽车管理系统的方案。文章介绍了共享汽车管理系统的系…

ASP.NET Core 路由规则,自定义特性路由 ,IActionConstraint 路由约束 总结 mvc

资料 资料 路由服务 路由服务是在 Program.cs 中使用 builder.Services.AddRouting()注册的&#xff0c; 只是默认在 builder 之前已经注册过了&#xff0c;无需我们再次注册。 AddRouting()方法必须在 UseRouting()方法之前运行&#xff0c;它是路由的基础服务。 MapContro…

linux基础——详细篇

免责声明 学习视频来自B 站up主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下代码、网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 linux 基础命令重现 cd(切…

Prosre:一款直观的协议发送模拟软件

Proser 是一款直观的协议编辑、发送端模拟软件。 在涉及二进制协议通信的程序开发过程中&#xff0c;我们经常会通过助手类工具编写协议来验证自己的代码&#xff0c;但这些助手对于大协议的编辑非常不友好&#xff0c;这时Proser会协助你轻松的完成测试。 特点 数据直接表达…

常见 HTTP 状态码分类和解释及服务端向前端返回响应时的最完整格式

目前开发的项目很大程度上是为明年的国产化做准备了&#xff0c;所以借这个机会把用了十年的自研系统全部重写&#xff0c;订立更严格的规范&#xff0c;本文记录一下返回格式及对应状态码。 常见 HTTP 状态码及解释 HTTP 状态码用于表示客户端请求的响应状态&#xff0c;它们…

【DL】YOLO11 OBB目标检测 | 模型训练 | 推理

本文进行YOLO11的旋转目标检测任务,旋转目标检测能够更精确地定位和描述那些非水平排列的目标,比如倾斜的飞机、船舶等。在原始的目标检测中,添加一个角度预测,实现定向边界框检测。 话不多说,先来个效果图!!! YOLO11中的旋转目标检测的特点 ▲更精确的定位:通过使用…

自动泊车端到端算法 ParkingE2E 介绍

01 算法介绍 自主泊车是智能驾驶领域中的一项关键任务。传统的泊车算法通常使用基于规则的方案来实现。因为算法设计复杂&#xff0c;这些方法在复杂泊车场景中的有效性较低。 相比之下&#xff0c;基于神经网络的方法往往比基于规则的方法更加直观和多功能。通过收集大量专家…

2025斯诺克器材与用品展,2025郑州台球器材展会3月举办

立足中原&#xff0c;辐射全国&#xff0c;壹肆柒2025中国&#xff08;郑州&#xff09;国际台球产业博览会&#xff0c;展位招商正在进行&#xff1b; 2025中国&#xff08;郑州&#xff09;国际台球产业博览会&#xff08;壹肆柒台球展&#xff09; The 2025 China (Zhengzh…

单调栈—acwing

一、题目&#xff1a; AcWing 830. 单调栈 - AcWing 暴力算法思想 双指针算法&#xff0c;本质上是比较操作&#xff0c;两个循环&#xff0c;时间复杂度高。通过栈可以一次遍历。 可以知道&#xff0c;只要前面有一个小于我的数&#xff0c;就可以。如果前面的数&#xff…

Ingress nginx 公开TCP服务

文章目录 背景搞起拓展( PROXY Protocol )参考 背景 公司业务繁多&#xff0c; HTTP、GRPC、TCP多种协议服务并存&#xff0c;Kubernetes流量入口复杂&#xff0c;所以萌生了通过LoadBalancer Ingress-nginx 的方式完全的结果入口流量&#xff0c;当然在高并发的场景下可以对…

小白投资理财 - 看懂 MACA K线图

小白投资理财 - 看懂 MACA K线图 什么是 MACDMACD 主要有三种用法第一是看快线和慢线两个线的位置第二是观察两条线交叉的情况第三就是通过观察 BAR 柱状图可预判该股市的走向例子 MACD 缺点总结 股市茫茫大海, 打开 K 线图, 几时开始入场, 几时应该退场傻傻不知道,没有一个指标…