讲师中心 微信公众号
AI工具推荐 视频效率加速

C++ atomic原子操作 C++ 无锁编程基础与内存序【并发编程】

阿辰同学_8711

阿辰同学_8711

发布时间:2026-01-31 13:53:46

|

847人浏览过

|

来源于php中文网

原创

默认内存序为memory_order_seq_cst,最严格安全但性能开销大;乱改易致数据竞争,仅独立计数器可用relaxed;acquire/release须配对用于同步;weak版compare_exchange因伪失败更轻量,需循环使用;fence仅在混合原子与非原子变量时必要;volatile无同步语义,不可替代atomic。

c++ atomic原子操作 c++ 无锁编程基础与内存序【并发编程】

atomic 的默认内存序为什么不能乱改

默认构造的 std::atomic<t></t> 使用 memory_order_seq_cst,这是最严格也最安全的顺序。它保证所有线程看到的原子操作顺序一致,且与非原子内存访问形成全序。但代价是可能触发全局内存屏障(如 x86 上的 mfence),在高竞争场景下显著拖慢性能。

常见误操作是把所有 load()/store() 都改成 memory_order_relaxed,结果出现读到“过期值”或逻辑错乱——比如一个线程写完标志位和数据,另一个线程却先读到标志位 true,再读到未初始化的数据。

  • 仅当变量完全独立(如计数器、统计指标),且不参与同步逻辑时,才可用 memory_order_relaxed
  • memory_order_acquire 和 memory_order_release 必须配对使用:前者用于读标志位,后者用于写标志位,构成“发布-获取”同步关系
  • x86 架构下 acquire/release 几乎无额外开销,但 ARM/AArch64 必须插入 dmb 指令,不可忽略

compare_exchange_weak 为什么比 compare_exchange_strong 更常用

compare_exchange_weak 允许伪失败(spurious failure):即使当前值匹配,也可能返回 false。这在某些硬件(如 ARM、旧版 x86)上由 LL/SC(Load-Link/Store-Conditional)机制导致,属于正常行为,不是 bug。

它比 compare_exchange_strong 更轻量,尤其在循环重试场景中性能更好。几乎所有无锁数据结构(如 lock-free stack、queue)都用 weak 版本配合 do-while 循环。

立即学习“C++免费学习笔记(深入)”;

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 必须在循环中使用:do { ... } while (!a.compare_exchange_weak(expected, desired));
  • 不要用 weak 做一次性判断(比如“如果等于 X 就执行 Y”,不重试),否则可能跳过逻辑
  • strong 版本适合单次尝试、且失败代价高(如需要回滚复杂状态)的场景,但极少遇到

atomic_thread_fence 什么时候真得用,而不是靠 atomic 操作自带的序

std::atomic_thread_fence 是独立于任何 atomic 变量的全局内存屏障,只约束当前线程的内存访问顺序。它不操作数据,只起“围栏”作用。绝大多数情况不需要它——atomic<t>::load/store</t> 带内存序参数已足够。

真正需要它的典型场景是:混合使用原子变量和普通变量,并需跨变量建立同步。例如,用一个 std::atomic<bool></bool> 作为就绪标志,但实际数据存在普通 int 中:

// 线程 A
data = 42;
atomic_flag.store(true, std::memory_order_release);

// 线程 B
if (atomic_flag.load(std::memory_order_acquire)) {
    // 此处 data 一定可见 —— 但前提是线程 A 的 data=42 不被重排到 store 之后
    // 而 release/acquire 本身只约束 atomic_flag 的操作,不约束 data
    // 所以线程 A 需要:
    data = 42;
    std::atomic_thread_fence(std::memory_order_release);
    atomic_flag.store(true, std::memory_order_relaxed);
}
  • 除非你在手动管理非原子变量的可见性,否则别碰 atomic_thread_fence
  • memory_order_seq_cst fence 是最强的,但它会阻塞所有后续内存操作,慎用
  • 编译器可能把普通变量访问优化掉或重排,fence 是告诉编译器“这里不能动”

std::atomic 和 volatile bool 的根本区别在哪

volatile 只禁用编译器优化(如缓存到寄存器),不提供任何线程同步语义;std::atomic<bool></bool> 则同时禁止编译器重排 + 生成必要硬件屏障 + 提供原子读写保证。

用 volatile bool 实现“停止标志”在单核或简单场景下看似有效,但在多核、开启 O2 优化、或遇到 StoreBuffer(如 x86 的 store forwarding)时大概率失效。

  • 哪怕只是做 while(!flag) {} 这种轮询,也必须用 std::atomic<bool></bool>,且 load 建议至少用 memory_order_acquire
  • volatile 在 C++ 并发中基本没用,除了映射硬件寄存器等极少数场景
  • 注意:std::atomic<bool></bool> 不一定编译成锁,多数平台用单条指令(如 x86 的 lock xchg 或 mov + barrier)
C++ 原子操作的难点不在语法,而在理解每个内存序背后的实际硬件行为和编译器意图。写错一个序,可能在你的机器上永远不暴露问题,换台 ARM 服务器或加个编译器版本就崩溃。

热门AI工具

更多
咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

354

2023.09.25

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

354

2023.09.25

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6979

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3345

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4368

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2965

2025.08.29

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

814

2025.10.23

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2741

2023.12.01

Uvicorn 报错与问题解决教程
Uvicorn 报错与问题解决教程

本专题汇总了Uvicorn服务器常见问题与报错解决的教程合集,涵盖启动失败、端口占用、模块导入错误、事件循环冲突及热重载失效等典型故障的排查思路。同时整理了多进程与Worker配置、SSL/HTTPS证书报错、跨域与代理配置等实战解决方案,助你快速定位并解决Uvicorn运行中的各类问题。

0

2026.11.02

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn