c++ std::atomic如何保证原子性 c++ CAS操作原理【底层】

发布时间 - 2026-01-01 00:00:00    点击率:
std::atomic的原子性由编译器生成特定CPU指令(如x86的lock、ARM的ldxr/stxr)与硬件共同实现,CAS是核心原语;compare_exchange_weak允许伪失败,compare_exchange_strong无伪失败;内存序控制可见性而非原子性。

std::atomic 的原子性不是靠 C++ 语言本身“保证”的,而是通过编译器生成特定的底层指令(如 x86 的 lock 前缀指令、ARM 的 ldxr/stxr 等)+ CPU 硬件支持共同实现的。CAS(Compare-And-Swap)是其中最核心的原语,它的原子性直接由 CPU 提供。

CPU 级别的原子操作支持

现代 CPU 在硬件层面提供了对单条内存访问指令的原子保障,但仅限于满足对齐、大小等条件的简单读写(如 4 字节对齐的 int)。而像“读-改-写”这类复合操作(例如 i++),天然不是原子的——中间可能被中断或并发修改。为此,CPU 提供了专门的原子指令:

  • x86/x64:使用 lock cmpxchg 指令实现 CAS;lock 前缀会锁定总线或缓存行(取决于架构和操作数大小),阻止其他核心/线程在同一时间修改同一缓存行。
  • ARM64:使用 ldxr(load-exclusive) + stxr(store-exclusive)配对。CPU 会标记某地址为“独占监视”,后续 stxr 成功当且仅当该地址未被其他核心修改过——失败则需重试。
  • RISC-V:类似 ARM,用 lr.w / sc.w(load-reserved / store-conditional)机制。

std::atomic::compare_exchange_weak/strong 的底层行为

这两个函数最终映射到上述 CPU 指令。区别在于:

  • compare_exchange_weak 允许“伪失败”(spurious failure):即使预期值匹配,也可能因底层机制(如 ARM 的独占监视被意外清除)返回 false。适合循环重试场景,性能略高。
  • compare_exchange_strong 保证:只要预期值匹配,就一定成功(无伪失败)。但某些平台(如早期 ARM)需额外检查+重试模拟,开销稍大。

典型用法是循环尝试:

int expected = val.load();
while (!val.compare_exchange_weak(expected, desired)) {
  // expected 已被更新为当前实际值
}

内存序(memory order)不是原子性,但影响可见性

原子性只解决“执行不中断”,不解决“结果何时对其他线程可见”。std::memory_order 控制编译器重排和 CPU 指令重排,以及缓存同步时机:

  • memory_order_relaxed:只保证该操作自身原子,不约束前后内存访问顺序,也不触发 cache coherency 同步(最快,适合计数器等无需同步语义的场景)。
  • memory_order_acquire(读)/memory_order_release(写):构成“获取-释放”同步,保证本线程中该操作前后的内存访问不会跨过它重排,并在多核间建立 happens-before 关系。
  • memory_order_seq_cst(默认):最强语义,所有线程看到的操作顺序一致,相当于全局顺序锁,性能开销最大。

编译器与运行时的协作

std::atomic 对象在编译期会被标记为不可分割访问(禁止拆解为多个 mov 指令),并根据模板参数类型选择对应宽度的原子指令(如 atomic → 32 位指令)。对于不支持原生原子操作的类型(如过大结构体),std::atomic 会退化为内部加锁(如 mutex),此时原子性由互斥量保证,而非硬件指令——但这已不属于“无锁原子操作”范畴。


# app  # 字节  # ai  # c++  # 区别  # 无锁  # red  # 架构  # while  # 结构体  # int  # 循环  # Conditional  # 线程  # 并发  # 对象  # 重试  # 多核  # 而非  # 也不  # 见性  # 多个  # 已被  # 并在  # 这两个  # 这类 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Swift中swift中的switch 语句  如何快速选择适合个人网站的云服务器配置?  如何用好域名打造高点击率的自主建站?  如何在香港免费服务器上快速搭建网站?  如何确认建站备案号应放置的具体位置?  EditPlus中的正则表达式实战(5)  如何选择可靠的免备案建站服务器?  HTML透明颜色代码在Angular里怎么设置_Angular透明颜色使用指南【详解】  Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决  Laravel如何优化应用性能?(缓存和优化命令)  LinuxShell函数封装方法_脚本复用设计思路【教程】  如何快速配置高效服务器建站软件?  PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑  图册素材网站设计制作软件,图册的导出方式有几种?  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能  php增删改查怎么学_零基础入门php数据库操作必知基础【教程】  如何安全更换建站之星模板并保留数据?  Android okhttputils现在进度显示实例代码  香港服务器租用每月最低只需15元?  Swift中switch语句区间和元组模式匹配  微信小程序 wx.uploadFile无法上传解决办法  网站制作壁纸教程视频,电脑壁纸网站?  实例解析Array和String方法  高端智能建站公司优选:品牌定制与SEO优化一站式服务  北京企业网站设计制作公司,北京铁路集团官方网站?  猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知  Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑  宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程  Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能  UC浏览器如何设置启动页 UC浏览器启动页设置方法  悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】  如何用PHP快速搭建高效网站?分步指南  如何在万网自助建站平台快速创建网站?  如何在香港服务器上快速搭建免备案网站?  如何快速重置建站主机并恢复默认配置?  在线制作视频网站免费,都有哪些好的动漫网站?  Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】  Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  VIVO手机上del键无效OnKeyListener不响应的原因及解决方法  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  Laravel控制器是什么_Laravel MVC架构中Controller的作用与实践  使用豆包 AI 辅助进行简单网页 HTML 结构设计  如何快速生成橙子建站落地页链接?