atomics-and-ordering
原子与内存序(Acquire/Release/SeqCst)
为什么需要原子
在并发下,普通读写可能被编译器/CPU 重排,导致数据竞争与可见性问题。原子操作提供“不可分割”的读改写与可见性保证。
常用原子类型
AtomicBool/AtomicIsize/AtomicUsize/AtomicI64/...
AtomicPtr<T>
(指针原子)
内存序(Ordering)
- Relaxed:仅保证原子自身的原子性,不提供跨线程的顺序关系。
- Acquire:读端获取,禁止其后操作重排到前面;与 Release 搭配形成“同步边”(happens-before)。
- Release:写端释放,禁止其前操作重排到后面。
- AcqRel:读改写操作的获取+释放。
- SeqCst:最强保证,所有 SeqCst 操作在全局单序(total order)中一致。
示例:经典消息传递(message passing)
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
static DATA: AtomicUsize = AtomicUsize::new(0);
static FLAG: AtomicUsize = AtomicUsize::new(0);
fn main() {
let t = thread::spawn(|| {
DATA.store(42, Ordering::Relaxed);
FLAG.store(1, Ordering::Release); // 发布
});
while FLAG.load(Ordering::Acquire) == 0 {} // 获取
assert_eq!(DATA.load(Ordering::Relaxed), 42); // 可见
t.join().unwrap();
}
compare_exchange 与弱 CAS
compare_exchange(expected, new, success, failure)
:在匹配expected
时用success
序;失败用failure
序。compare_exchange_weak
可能虚假失败,需在循环中重试;某些架构上更高效。
Fences(栅栏)
atomic::fence(Ordering::SeqCst/Acquire/Release)
用于在无需具体原子读写时建立顺序边。
反模式与注意
- 混用原子与非原子访问同一位置(数据竞争)
- 过度使用 SeqCst,降低性能;但也不要使用过弱的序导致竞态
- 忽略“拆箱”问题:将多个相关字段拆成独立原子可能打破不变量,需要额外同步
工具
loom
:枚举并发交错测试算法正确性ThreadSanitizer
:检测数据竞争(注意对 Rust/async 的支持范围)