1. 为什么需要内存排序
在多线程编程中,编译器和处理器会进行各种优化(如指令重排序)来提供性能。内存排序定义了这些优化在多线程环境中的行为。
Rust中的内存排序级别
Rust通过std::sync::atomic::Ordering
提供了几种内存排序级别:
2.1 Relaxed
- 最弱的内存排序
- 只保证当前操作的原子性
- 不保证操作之间的顺序
- 适用场景:简单的计数器、统计信息
use std::sync::atomic::{AtomicUsize, Ordering};
let counter = AtomicUsize::new(0);
counter.fetch_add(1, Ordering::Relaxed);
2.2 Release和Acquire
Release
:- 写屏障,确保Release操作之前的所有内存操作(读/写)都完成
- 可见性保证,确保这些修改对其他线程可见
- 发布数据到共享内存,标记数据准备就绪
Acquire
- 读屏障:确保在Acquire操作之后的所有内存操作(读/写)都能看到之前Release操作的所有修改
- 可见性保证:确保看到其他线程Release操作之前的所有修改
- 从共享内存读取数据,检查数据是否就绪
2.3 AcqRel
- 组合语义,同时具有
Release
和Acquire
的语义
2.4 Seqcst
- 最强保证:除了
Acquire/Release
外,还保证全局一致性 - 额外保证:
- 所有线程看到的操作顺序一致,所有线程看到的操作顺序是一致的
- 要么看到 (3) -> (1) -> (4) -> (2)
- 要么看到 (1) -> (3) -> (2) -> (4)
- 建立全局操作顺序
- 所有线程看到的操作顺序一致,所有线程看到的操作顺序是一致的
小结
Relaxed
是只针对原子变量的,其他内存排序是针对共享内存的,充当着内存屏障的作用。