当前位置: 首页 > backend >正文

C++ 原子操作的内存序(memory ordering)

std::memory_order 用于指定原子操作的内存顺序约束,控制多线程环境下的操作可见性和执行顺序。

1. memory_order_relaxed(松散顺序)

特点

  • 无同步或顺序约束:仅保证原子操作的原子性,不保证操作顺序。

  • 性能最高:适合不需要同步的场景(如计数器)。

示例

std::atomic<int> counter{0};void increment() {counter.fetch_add(1, std::memory_order_relaxed); // 无同步保证
}

适用场景

  • 统计计数、无竞争场景(如性能计数器)。


2. memory_order_consume(消费顺序)

特点

  • 比 acquire 更弱:仅保证依赖该原子变量的操作不被重排。

  • 用于数据依赖链(如指针解引用)。

示例

std::atomic<int*> ptr{nullptr};
int data = 0;void producer() {data = 42;ptr.store(&data, std::memory_order_release); // 发布指针
}void consumer() {int* p;while (!(p = ptr.load(std::memory_order_consume))) { // 消费指针// 等待}assert(*p == 42); // 仅保证 p 依赖的操作有序
}

适用场景

  • 适用于指针或数据依赖的场景(比 acquire 更高效)。


3. memory_order_acquire(获取顺序)

特点

  • 与 release 配对,确保后续操作不会重排到 acquire 之前。

  • 读取同步:保证看到 release 之前的修改。

示例

std::atomic<bool> ready{false};
int data = 0;void producer() {data = 42;ready.store(true, std::memory_order_release); // 发布数据
}void consumer() {while (!ready.load(std::memory_order_acquire)) { // 等待 release// 自旋}assert(data == 42); // 保证看到 data = 42
}

适用场景

  • 锁的获取、线程间数据同步。


4. memory_order_release(释放顺序)

特点

  • 与 acquire 配对,确保之前的操作不会重排到 release 之后。

  • 写入同步:保证修改对 acquire 线程可见。

示例

std::atomic<int> flag{0};
int data = 0;void producer() {data = 42;flag.store(1, std::memory_order_release); // 确保 data = 42 在 flag = 1 之前
}void consumer() {while (flag.load(std::memory_order_acquire) != 1) { // 等待 release// 自旋}assert(data == 42); // 保证看到 data = 42
}

适用场景

  • 锁的释放、线程间数据发布。


5. memory_order_acq_rel(获取-释放顺序)

特点

  • 同时具备 acquire 和 release 语义

    • 如果是读-修改-写(RMW)操作(如 fetch_add),则:

      • 读取部分 采用 acquire 语义(防止后续操作重排到前面)。

      • 写入部分 采用 release 语义(防止前面操作重排到后面)。

  • 适用于 CAS(Compare-And-Swap)等操作

示例

std::atomic<int> counter{0};void increment() {counter.fetch_add(1, std::memory_order_acq_rel); // 读-修改-写
}

适用场景

  • 自旋锁、无锁数据结构(如队列、栈)。


6. memory_order_seq_cst(顺序一致性)

特点

  • 最强约束:所有 seq_cst 操作按全局顺序执行(类似互斥锁)。

  • 默认选项(如果不指定内存序,原子操作默认使用 seq_cst)。

  • 性能较低,但最安全。

示例

std::atomic<bool> x{false}, y{false};
int z = 0;void write_x() {x.store(true, std::memory_order_seq_cst); // 全局可见顺序
}void write_y() {y.store(true, std::memory_order_seq_cst); // 全局可见顺序
}void read() {while (!x.load(std::memory_order_seq_cst)) {}if (y.load(std::memory_order_seq_cst)) {z++; // 保证 x 和 y 的修改顺序一致}
}

适用场景

  • 需要严格顺序的场景(如 Dekker 算法、Peterson 锁)。

7. 总结

内存序作用适用场景
relaxed仅保证原子性,无顺序约束计数器、无竞争统计
consume仅保证依赖该原子变量的操作有序指针发布(较少使用)
acquire保证后续操作不会重排到它之前(读同步)锁获取、数据同步
release保证之前操作不会重排到它之后(写同步)锁释放、数据发布
acq_rel同时具备 acquire 和 release(用于 RMW 操作)自旋锁、无锁数据结构
seq_cst全局顺序一致(最强约束,性能最低)需要严格顺序的算法

 

http://www.xdnf.cn/news/3070.html

相关文章:

  • ptpx常用操作
  • 企业选择IT技术人员外包能解决哪些问题
  • 【Axure高保真原型】动态地图路线
  • 三维引擎HOOPS SDK适配Linux ARM64,对国产工业软件意味着什么?
  • 深入剖析扩散模型对镜子反射理解局限:MirrorVerse 项目改进数据集与训练方法以提升反射处理表现的研究
  • 基于STM32、HAL库的ATECC608A安全验证及加密芯片驱动程序设计
  • LDO中反向二极管作用
  • 【每天一个知识点】GPU(图形处理单元)和CPU(中央处理单元)
  • Java—— 四道算法经典题
  • jthread是否可以完全取代thread?
  • 共享货源系统,多商户独立站助力行业资源整合
  • 掌握 Linux 中 SELinux 的强制访问控制机制和 iptables、 firewalld 两种防火墙以及他们的使用方法
  • 双系统,bios默认设置启动ubuntu+ubuntu改启动grub设置
  • 学习在暑假避免躺平和内卷(马井堂)
  • FlexNoC随手记
  • 双差分探头法精准测量共模电压的技术解析
  • g4f api报错:ImportError: cannot import name ‘model_validator‘ from ‘pydantic‘
  • 【探寻C++之旅】第十二章:异常
  • AI国学智慧语录视频,条条视频10W+播放量
  • 10.学习笔记-MyBatisPlus(P105-P110)
  • Educational Codeforces Round 178 (Rated for Div. 2)E. Unpleasant Strings
  • java执行linux命令查询信息
  • 在Java中基于Geotools对PostGIS数据库的空间查询实践
  • MySQL 连接池 (Pool) 常用方法详解
  • 创建Python虚拟环境
  • mybatis传递多个不同类型的参数到mapper xml文件
  • MAC安装unar并解压.rar文件
  • 实现在h5中添加日历提醒:safari唤起系统日历,其它浏览器跳转google日历
  • 数据资产如何产生价值与发挥价值:从认知到实践的全景指南
  • 智慧交警系统架构设计方案