为何__ATOMIC_SEQ_CST无法阻止CPU重排?附代码实例分析
关于__ATOMIC_SEQ_CST原子操作防CPU重排的机制解析
根据GCC定义,__ATOMIC_SEQ_CST类型的原子操作必须与所有其他__ATOMIC_SEQ_CST操作保持全局顺序。先看示例代码:
int test(int* num) { int m = __atomic_load_n(num, __ATOMIC_SEQ_CST); int z = __atomic_load_n(num, __ATOMIC_SEQ_CST); }
用x86-64 GCC 12.2编译后生成的汇编如下:
test: push rbp mov rbp, rsp mov QWORD PTR [rbp-24], rdi mov rax, QWORD PTR [rbp-24] mov eax, DWORD PTR [rax] mov DWORD PTR [rbp-4], eax mov rax, QWORD PTR [rbp-24] mov eax, DWORD PTR [rax] mov DWORD PTR [rbp-8], eax nop pop rbp ret
核心问题解答:阻止两次原子操作重排的机制
这里的关键在于x86-64架构本身的内存一致性模型:
- x86硬件天然禁止「load-load重排」——CPU绝对不会把后续的读操作提前到前面的读操作之前执行,尤其是针对同一内存地址的两次读,这种顺序性是硬件层面强制保证的。
- 对于针对同一地址的
__ATOMIC_SEQ_CSTload操作,GCC不需要额外插入mfence这类内存屏障指令,因为x86的硬件规则已经完全满足SEQ_CST对操作顺序的要求,CPU不可能对这两次读做重排。
如果是针对不同内存地址的__ATOMIC_SEQ_CST操作,编译器可能会插入内存屏障来维持全局顺序,但同一地址的场景下,硬件本身的规则就足够兜底了。
内容的提问来源于stack exchange,提问作者Moshe Levy
相关产品推荐
相关产品推荐

