《C++并发编程实战》提及memory_order_release与seq_cst同步,为何仍可指令重排?
为什么memory_order_release与seq_cst同步时,编译器/硬件还能重排指令?
先拎清楚一个关键:同步关系(synchronizes-with)≠ 禁止所有指令重排。《C++并发编程实战》里提到的release和seq_cst的同步,说的是特定操作间的可见性保证,不是把所有相关指令的顺序焊死。
具体拆解下:
- 带
memory_order_release的存储操作,只限制它自己和它之前的读写操作不能乱序——也就是说release操作不能被放到它前面的任何读写之后,但它之后的无关读写操作,编译器完全可以挪到它前面,只要这些操作和同步用的变量没数据/控制依赖。 memory_order_seq_cst虽然要求全局顺序一致,但它的约束是针对所有seq_cst操作的全局总序,对于非seq_cst的操作,只要不破坏这个全局总序,编译器和硬件照样能做合法重排。
举个实际场景的例子:线程A先执行a = 1;,再执行store(x, memory_order_release);线程B通过load(x, memory_order_seq_cst)成功同步后读取a。这种情况下,同步关系保证线程B能看到a=1,但编译器绝对不能把a=1和store(x, release)的顺序调换——这会破坏可见性。但如果线程A在store(x, release)之后还有个b=2;,编译器把b=2挪到store(x, release)前面是完全允许的,因为b和同步变量x没有关联,也不会影响线程B同步后的可见性。
硬件层面也是同样的逻辑,比如ARM这类弱内存模型的CPU,会根据自身的内存规则做重排优化,只要不违反C标准对release/seq_cst的约束就行。毕竟指令重排是编译器和硬件提升程序性能的核心手段之一,C内存模型只会卡死保证多线程程序正确性的最小必要规则,不会一刀切禁止所有可能的重排。
内容的提问来源于stack exchange,提问作者Rupa
相关产品推荐
相关产品推荐

