C++11 定义了 6 种原子操作的内存序(memory order) ,用于控制多线程中的可见性和重排序规则。如下是六种内存序的简介、特点和适用场景:
六种内存序一览表
| 内存序名称 | 描述 / 特点 | 是否同步其他线程可见性 | 是否禁止重排序 | 使用场景示例 |
|---|---|---|---|---|
memory_order_relaxed |
最弱序,无同步,无重排序限制 | 不同步其他线程 | 允许重排序 | 统计计数器、自增编号等 |
memory_order_consume |
数据依赖同步(已废弃) | 实际等同 acquire | 编译器优化误差多 | 几乎不用 |
memory_order_acquire |
获取操作,防止之后操作被重排序到前面 | 同步前写可见 | 禁止之后操作重排序 | load 时读取同步数据 |
memory_order_release |
释放操作,防止之前操作被重排序到后面 | 同步后读可见 | 禁止之前操作重排序 | store 时写入同步数据 |
memory_order_acq_rel |
同时具有 acquire 和 release 效果 | 双向同步 | 全部禁止重排序 | 常用于 fetch_add 等读改写操作 |
memory_order_seq_cst |
最强序,全局顺序一致性 | 所有线程可见 | 强制全局顺序 | 多线程安全,易理解但性能最低 |
实用说明
memory_order_relaxed`
- 不做任何同步,仅保证原子性。
- 不保证其他线程看到值变化的顺序。
cpp
std::atomic<int> x(0);
x.store(1, std::memory_order_relaxed); // 线程B可能看不到
memory_order_acquire`
- 常用于
load操作。 - 保证:本线程对该变量之后的操作不会被提到它前面。
cpp
int data = 0;
std::atomic<bool> ready = false;
// 线程A
data = 42;
ready.store(true, std::memory_order_release);
// 线程B
while (!ready.load(std::memory_order_acquire));
std::cout << data; // 始终能看到 data = 42
memory_order_release`
- 常用于
store操作。 - 保证:本线程在此之前的写入对其他 acquire 线程可见。
memory_order_acq_rel`
- 用于 读-改-写原子操作 :如
fetch_add、compare_exchange - 保证:在操作前后都不能乱序
cpp
counter.fetch_add(1, std::memory_order_acq_rel);
memory_order_seq_cst`
- "Sequential Consistency":最直观的并发语义
- 保证所有线程看到的修改具有全局一致顺序
- 对于简单并发程序是最安全选择,但性能可能不理想
memory_order_consume`
- 理论上只依赖"数据依赖性",但已在实践中废弃(比如 gcc/clang 实际当作 acquire 处理)
小结
Relaxed < Acquire/Release < Acq_Rel < Seq_Cst
(低同步/快) → (高同步/慢)
: 基础能力系列
: 区块链知识系列
: 密码学系列
: 零知识证明系列
: 共识系列
: 公链调研系列
: BTC系列
: 以太坊系列
: EOS系列
: Filecoin系列
: 联盟链系列
: Fabric系列
: 智能合约系列
: Token系列