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 | 全局顺序一致(最强约束,性能最低) | 需要严格顺序的算法 |