图解Modern Cpp内存序
C++ 内存序(Memory Order)定义了多线程环境下对共享内存的操作顺序和可见性规则. 它是 C++ 原子操作(std::atomic
)的重要组成部分, 允许开发者在性能和线程安全之间进行权衡.
为什么需要内存序?
在多线程编程中, 现代 CPU 和编译器会进行指令重排序, 以优化性能. 指令重排序可能导致线程间的操作顺序与程序逻辑不一致, 从而引发数据竞争. C++ 的内存序通过提供一组规则, 确保线程间操作的正确性, 同时尽量减少性能损失.
内存序的分类
C++ 提供了六种内存序, 分别针对不同的同步需求和性能优化:
内存序的作用
指令重排序限制
relaxed
: 允许指令完全重排序.acquire
: 禁止读取操作重排到当前操作之前.release
: 禁止写入操作重排到当前操作之后.seq_cst
: 严格禁止所有重排序.
跨线程可见性
acquire
: 确保当前线程可以看到其他线程释放的内存操作.release
: 确保当前线程的操作对其他线程可见.
样例分析
完全乱序: memory_order_relaxed
允许线程独立执行, 不保证顺序或可见性, 仅保证操作原子性.
可能有如下 4 种输出:
读写同步: memory_order_acquire
和 memory_order_release
用于线程间同步, 确保操作的可见性和顺序.
可能的执行结果:
一致性 memory_order_seq_cst
最严格的内存序, 确保全局顺序一致性.
可能的执行步骤
结果: 输出顺序严格受控, 但性能最低.
6. 内存序的权衡
- 性能优先:
relaxed
内存序提供最高性能, 但不保证顺序和可见性. - 正确性优先:
acquire
/release
是实际编程中常用的同步机制. - 简单实现:
seq_cst
是默认选择, 但代价是性能下降.
总结
- C++ 内存序是原子操作的关键组成部分, 用于平衡性能和同步需求.
- 默认使用
memory_order_seq_cst
, 在性能敏感场景中使用relaxed
或acquire/release
. - 结合实际多线程需求合理选择内存序, 有助于写出高效且安全的代码.