0

0

C++的std::memory_order详解_C++原子操作中的内存屏障与可见性模型

穿越時空

穿越時空

发布时间:2025-12-05 13:19:03

|

635人浏览过

|

来源于php中文网

原创

C++中std::memory_order通过控制内存访问顺序来确保多线程数据可见性和操作顺序,六种内存序提供不同强度的同步保证:relaxed仅保原子性;acquire防止后续读写重排到前面;release防止前面读写重排到后面;acq_rel兼具两者;seq_cst提供全局顺序一致。常见应用包括用relaxed实现高性能计数器,acquire-release配对实现无锁同步,如标志位通知,而seq_cst为默认最安全选项,适合不熟悉内存模型的开发者,在保证正确性的同时需权衡性能开销。

c++的std::memory_order详解_c++原子操作中的内存屏障与可见性模型

在C++的多线程编程中,原子操作和内存顺序(memory order)是控制并发行为的核心机制。std::memory_order 用于指定原子操作周围的内存访问如何被排序,从而影响数据可见性和执行顺序。理解这些内存顺序选项,有助于编写高效且正确的并发代码。

内存顺序的基本作用

原子操作本身保证了对单个变量的读写是不可分割的,但不控制其他内存操作的顺序。CPU 和编译器为了优化性能,可能会重排指令。std::memory\_order 允许程序员插入内存屏障(memory barrier),限制这种重排,确保特定的同步语义。

C++ 提供了六种 memory order 枚举值:

  • std::memory_order_relaxed:最弱的顺序约束,只保证原子性,不提供同步或顺序保证。
  • std::memory_order_consume:依赖该原子操作结果的后续读写不能被重排到其前面(目前很少使用,多数场景推荐用 acquire)。
  • std::memory_order_acquire:用于读操作,保证该操作之后的读写不会被重排到它前面。
  • std::memory_order_release:用于写操作,保证该操作之前的读写不会被重排到它后面。
  • std::memory_order_acq_rel:同时包含 acquire 和 release 语义,适用于读-修改-写操作。
  • std::memory_order_seq_cst:最强的顺序模型,提供全局顺序一致性,所有线程看到的操作顺序一致。

常见内存顺序的应用场景

不同的 memory order 适用于不同同步需求,选择合适的可以兼顾性能与正确性。

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

relaxed 内存序:计数器场景

当只需要原子性而不需要同步时,可以用 relaxed。例如多个线程递增一个计数器:

std::atomic counter{0};

void increment() {
    counter.fetch_add(1, std::memory_order_relaxed);
}

这里不关心其他内存操作的顺序,只保证 counter 的修改是原子的。

acquire-release 模型:实现锁或标志同步

这是最常见的非默认内存序组合。一个线程 release 写入标志,另一个线程 acquire 读取该标志,可建立同步关系。

虎课网
虎课网

虎课网是超过1800万用户信赖的自学平台,拥有海量设计、绘画、摄影、办公软件、职业技能等优质的高清教程视频,用户可以根据行业和兴趣爱好,自主选择学习内容,每天免费学习一个...

下载
std::atomic ready{false};
int data = 0;

// 线程1:发布数据
data = 42;
ready.store(true, std::memory_order_release);

// 线程2:等待并读取数据
while (!ready.load(std::memory_order_acquire)) {
    // 等待
}
assert(data == 42); // 不会触发,data 的写入对当前线程可见

release 保证 data = 42 不会被重排到 store 后面,acquire 保证 load 后的读取能看到之前 release 前的所有写入。

seq_cst:默认且最安全的选择

所有原子操作默认使用 std::memory_order_seq_cst。它提供了类似“所有线程都看到相同操作序列”的直观行为。

ready.store(true); // 默认是 seq_cst

虽然安全,但在某些架构(如 ARM、PowerPC)上性能开销较大,因为需要全局内存屏障。

内存屏障与可见性的关系

内存顺序的本质是控制“可见性”和“顺序”。没有适当的 barrier,一个线程的写操作可能长时间对另一个线程不可见,或观察到不合逻辑的操作顺序。

acquire-release 配对建立了“synchronizes-with”关系,使得一个线程的修改能被另一个线程可靠观察到。而 relaxed 操作之间无法建立这种关系,不适合同步用途。

seq_cst 在所有原子变量间引入一个全局总序,避免了复杂推理,适合对并发模型不熟悉的开发者。

基本上就这些。合理使用 memory order 能在保证正确性的同时减少不必要的性能损耗。关键是根据同步需求选择最弱的有效约束。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

143

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

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

5

2026.01.21

C++多线程相关合集
C++多线程相关合集

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

11

2026.01.21

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

9

2026.01.22

html编辑相关教程合集
html编辑相关教程合集

本专题整合了html编辑相关教程合集,阅读专题下面的文章了解更多详细内容。

56

2026.01.21

三角洲入口地址合集
三角洲入口地址合集

本专题整合了三角洲入口地址合集,阅读专题下面的文章了解更多详细内容。

30

2026.01.21

AO3中文版入口地址大全
AO3中文版入口地址大全

本专题整合了AO3中文版入口地址大全,阅读专题下面的的文章了解更多详细内容。

393

2026.01.21

妖精漫画入口地址合集
妖精漫画入口地址合集

本专题整合了妖精漫画入口地址合集,阅读专题下面的文章了解更多详细内容。

116

2026.01.21

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.3万人学习

C 教程
C 教程

共75课时 | 4.2万人学习

C++教程
C++教程

共115课时 | 13.3万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号