发布时间:2026/9/3 17:04:29
C/C++——atomic小记 CAS操作CAS操作就是“compare_and_swap”比较和交换。这是实现atomic原子操作的基石在一些平台下CAS本身就是一个原子指令因此是原子的在另一些平台下CAS是硬件模拟原子的不止由一个指令组成。CAS的weak和strongCAS在C中有两种接口compare_exchange_weak 和 compare_exchange_strong 一般我们说weak是不安全但是高效的、strong是安全但是不效的。只有在多指令CAS下才有weak和strong这个说法如果是单指令CAS不会有这种区别。在多指令CAS中操作分为三步第一步LL (Load-Linked) - 读取值并标记这个内存地址 LL R1, [内存地址] ; R1 100开始监视这个地址 第二步比较 CMP R1, 期望值 ; 100 100是的 第三步SC (Store-Conditional) - 条件存储 SC R2, [内存地址] ; 尝试写入新值 ; 但如果这个地址被打扰过写入失败 ; 返回 0失败看懂了吗也就是说在第一步而第三步中间可能有其他线程会直接修改变量值因为缓存一致性对于本线程来说这个变量的寄存器值失效了所以无法写入所以执行失败。这种判断相等之后依旧执行失败的现象叫做“伪失败”正常失败是在第一步的时候比较失败这是正常的但是伪失败是在我们已经赋予CAS原子性语义的情况下中间操作失败这是逻辑上的错误所以说如果我们直接使用compare_exchange_weak可能会出现伪失败最终导致数据不一致的情况。但是这是可以避免的// weak 版本 - 可能伪失败 while (!value.compare_exchange_weak(expected, newvalue)) { // 如果失败包括伪失败expected 会被更新为当前值 // 循环重试 }而compare_exchange_strong做了什么呢// strong 的内部实现伪代码 bool compare_exchange_strong(expected, desired) { // 内部循环调用 weak 版本 while (true) { bool success compare_exchange_weak(expected, desired); if (success) { return true; // 成功了 } // 失败有两种情况 if (expected ! actual_value) { return false; // 真失败值确实变了 } // 伪失败值没变继续循环重试 // expected 已经被更新为当前值还是原值 // 继续下一次尝试 } }实际上strong也是循环重试而compare_exchange_strong和compare_exchange_weak的性能差异就体现在多出来的两个条件判断上。strong为了维护CAS原子性的语义不能把两种失败都直接返回false因此在其内部做了判断区分。atomic无锁头插链表typedef struct node { node(int val,node* ne) { _val val; _next ne; } struct node* _next; int _val 0; }Node; atomicNode* head(nullptr); void func(int i) { Node* old head.load(); Node* newnode new Node(i,nullptr); do { newnode-_next old; } while (!head.compare_exchange_weak(old, newnode)); } int main() { int k 0; vectorthread arr; for (int i 0;i10;i) { arr.push_back(thread(func, k)); } for ( auto e:arr) { e.join(); } Node* cur head.load(); while(cur!nullptr) { cout cur-_val ; cur cur-_next; } cout endl; }atomic内存序一些时候为了优化程序效率会把指令顺序重排。对于指令乱序这块需要注意的是编译器只需要保证在单线程环境下执行的结果最终一致就可以了所以指令乱序在单线程环境下完全是允许的。但是编译器并不知道哪些数据是在线程间共享而且是有可能会被修改的这些是需要开发人员去保证的。而atomic这个类天生就是为多线程而生因此一旦你使用atomic那么就需要考虑内存序问题内存序就是限制本来可以重排的命令之间的顺序以保证多线程并发安全锁在内部其实也保证了内存序只是它封装起来了我们看不到atomic的操作比如说load比如说compare_exchange_weak都可以设置内存序以防止出错。1.memory_order_relaxed最宽松语义仅保证原子操作的原子性不提供任何同步或顺序约束重排限制无编译器和CPU可任意重排该操作周围的指令示例std::atomicint x(0); x.store(42, std::memory_order_relaxed); // 仅保证原⼦性2.memory_order_acquire获取语义语义这个内存序只可以在包含读操作的atomic操作中使用比如load比如exchange读操作之后可能本线程就要能执行了这个内存序保证读操作之后的所有读写操作都一定是在可以执行之后才执行的不能因为重排而打乱导致并发问题。重排限制防止后续操作读或写被提到该操作之前执行3.memory_order_release释放语义语义这个内存序只可以在包含写操作的atomic操作中使用比如storeexchange写操作之后其他线程就会被唤醒这个内存序保证写操作之前的所有读写操作都一定是被执行的防止被唤醒的线程访问出错。重排限制防止先前操作读或写被延迟到该操作之后执行示例​​​std::atomicbool flag(false); int data 0 // 线程 1 data 42; flag.store(true, std::memory_order_release); // 保证 data 42 在 flagtrue 之前可⻅ // 线程 2 while (!flag.load(std::memory_order_acquire)) {} std::cout data; // 保证看到 data 42上面是一个线程修改另一个线程负责打印的例子如果没有 std::memory_order_release 那么有可能flag的设置会在data赋值之前这样可能会造成线程2打印出0的错误结果。如果没有 std::memory_order_acquire 编译器可能会认为while循环和打印交换没什么影响因为在线程2的函数中data没有被修改因此出现错误。4.memory_order_acq_rel获取-释放混合语义同时具有acquire和release的语义一般用于同时进行读写操作的原子操作比如fetch_add。重排限制既防止前面的操作被移到之后也防止后面的操作被移到之前双向限制示例std::atomicint counter(0); int old counter.fetch_add(1, std::memory_order_acq_rel); // 既保证之前操作不会被重排到后面也保证之后操作不会被重排到前面5.memory_order_seq_cst顺序一致性默认语义所有线程看到的内存操作顺序完全一致全局顺序一致性重排限制最强限制完全禁止所有相关重排并提供全局同步点示例std::atomicint x(0); x.store(42, std::memory_order_seq_cst); // 默认模式 int value x.load(std::memory_order_seq_cst); // 所有线程保证看到相同顺序

相关新闻

2026/9/3 17:04:29

咨询系统有风险查询功能吗?能查合作方失信信息吗

合作方踩雷的代价,比想象中大咨询公司的业务离不开合作方:审核机构、供应商、渠道商,个个都要打交道。可合作方靠不靠谱,以前只能靠打听、靠感觉,等合作到一半出了问题,项目停摆、钱收不回来,损…

2026/9/3 17:04:29

手机控制嵌入式程序烧录:移动化方案与工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/3 16:59:28

嵌入式蒸烤微一体机选购安装全攻略:60L双风炉详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/3 17:19:31

现代前端如何重构已淘汰的腾讯WAP风格

简介:本资源是面向Web开发初学者与中级PHP开发者的一套仿腾讯WAP站点实战源码,旨在帮助用户快速搭建具备内容管理、论坛互动、广告投放及图书资讯等核心功能的移动端网站。资源包含2000个文件,主体为1990个txt配置与逻辑脚本(支撑…

2026/9/3 17:19:31

Godot UI架构理念搬到Unity:一场信号与节点树的设计实验

做过 Unity UI 的开发者,第一次打开 Godot 时往往会有一种很奇特的感受:做 UI 好像“少了一步”。不是功能变少了,而是整套 UI 心智模型换了。在 Unity 里,我们习惯了 Canvas 下面挂着许多带 RectTransform 的节点,用锚…

2026/9/3 17:19:31

零基础自学Unity一周路线:核心概念与首个Demo实战

如果你最近在技术社区逛得比较多,应该会看到不少类似的打卡帖子:“[27届]自学Unity一周成果”。很多大二、大三的同学,或者准备秋招、做毕设、参加比赛的同学,都会有同样的疑问:Unity 到底难不难?一周时间能…

2026/9/3 17:19:31

基于YOLOv8的交通信号灯通行规则识别系统

简介:本资源是一套面向计算机及相关专业本科生的毕业设计与期末大作业实践方案,聚焦于交叉路口交通信号灯状态识别与通行规则解析这一典型视觉感知任务,采用YOLOv8深度学习模型实现端到端检测与逻辑判断,兼顾学术规范性与工程可运…

2026/9/3 17:19:31

【计算机毕业设计单片机案例】基于 51 单片机的手动 / 自动双模式室内安防预警系统设计 基于 STM32 的温度、燃气、烟雾、火焰一体化监测控制系统(017606)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/9/1 16:02:17

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/3 14:29:47

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/3 14:30:35

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/3 0:02:06

零基础装 OpenClaw 小龙虾 AI:Windows 一键部署教程与避坑要点

Windows 部署 OpenClaw 完整教程|本地 AI 智能体 5 分钟落地,环境配置一次搞定 版本说明:Windows 3.1.0 / Mac 2.7.9 写在前面 近两年开源 AI 领域有一款被称作「数字员工」的工具持续走热,它就是 OpenClaw,圈内人更习…

2026/9/3 0:02:06

Hermes Agent 本地部署新方案:Windows 整合包减少依赖报错

Windows 本地部署 Hermes 太麻烦?这版一键包 5 分钟快速跑通 很多人想体验 Hermes Agent,但真正开始部署时,往往会卡在环境配置这一步。 需要安装各类依赖、调试运行环境、处理路径问题,还容易遇到命令行报错、系统拦截、文件缺…

2026/9/3 0:02:06

实测 OpenClaw 一键包,5 分钟完成本地自动化环境搭建

OpenClaw 本地 AI 自动化工具部署指南|使用一键包规避环境配置难题 痛点:部署 AI 自动化工具常常要处理 Python、Node.js 各类依赖,版本冲突、环境配置耗费大量时间,OpenClaw 提供一键安装包,降低部署门槛。 适配系统&…

2026/9/2 1:15:22

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/2 1:15:22

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/2 1:15:20

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…