关于 volatile 保证的有序性

2023-02-01 00:07:22 +08:00
 luxinfl

有个情况,感觉查出来的都不太对的样子。

volatile 写会在之前加上一个 StoreStore 屏障、在后面加上一个 StoreLoad 屏障。 StoreLoad 的屏障不是代表禁止 volatile 写与后面可能有的 volatile 读和写重排序吗?

但是好多博文的表格,在 volatile 写后面的普通读写都没有写 NO

是否能重排序 第二个操作 第二个操作 第二个操作
第一个操作 普通读 /写 volatile 读 volatile 写
普通读 /写 NO
volatile 读 NO NO NO
volatile 写 NO NO

所以到底可不可以重排

2569 次点击
所在节点    程序员
13 条回复
Azzsanjin
2023-02-01 00:59:02 +08:00
奶奶滴,真滴卷,没必要搞这个吧,谁用个 volidate 还考虑读写屏障
GeruzoniAnsasu
2023-02-01 01:25:32 +08:00
volatile 阻止编译器重排序

这与阻止 CPU 乱序执行

是两回事。
iseki
2023-02-01 02:37:28 +08:00
你最好说清楚是什么语言的 volatile ,Java 和 C 里的完全不一样
dangyuluo
2023-02-01 06:28:31 +08:00
C++里,volatile 只会起到两个作用:该变量不会被放进寄存器里,compiler will not reorder operations across the operation of this volatile variable.

你说的东西是 CPU 层面的乱序执行,volatile 并不能起到 mfense, lfense, sfense 的效果
Mogugugugu
2023-02-01 08:54:54 +08:00
StoreLoad 屏障禁止 volatile 写与后面可能有的 volatile 读和写重排序,与第二个操作的普通读写无关啊。
weidaizi
2023-02-01 09:57:52 +08:00
楼主没说明语言,c/c++ 和 c#/java 中的 volatile 语义是不一样的。
就 CPU 乱序执行来说:c/c++ 使用 volatile 是让编译器别来优化,但是并不提供多线程间的顺序和可见性保证;而如果是 c#/java ,使用 volatile 则可以保证变量在多线程间可见性,可以用于并发编程。
zifangsky
2023-02-01 10:52:40 +08:00
Java 中的 volatile 关键字应该只能保证原子性和可见性,有序性是不能保证的
leonshaw
2023-02-01 11:07:31 +08:00
默认你说的是 Java 。Spec 对 volatile 只要求了 release/acquire 语义以及 volatile 写 happens before 后续的 volatile 读。store-release 只需要前一个屏障,而后一个屏障是为了实现第二点 volatile 写-读保序,副作用是同时禁止了普通读写的重排。屏障不是 spec 的要求,只是一种实现方式。
e9pWeUbh9PGCnp95
2023-02-01 12:05:20 +08:00
c 标准原话
Every access (both read and write) made through an lvalue expression of volatile-qualified type is considered an observable side effect for the purpose of optimization and is evaluated strictly according to the rules of the abstract machine (that is, all writes are completed at some time before the next sequence point). This means that within a single thread of execution, a volatile access cannot be optimized out or reordered relative to another visible side effect that is separated by a sequence point from the volatile access

c 艹标准原话
Every access (read or write operation, member function call, etc.) made through a glvalue expression of volatile-qualified type is treated as a visible side-effect for the purposes of optimization (that is, within a single thread of execution, volatile accesses cannot be optimized out or reordered with another visible side effect that is sequenced-before or sequenced-after the volatile access. This makes volatile objects suitable for communication with a signal handler, but not with another thread of execution, see std::memory_order). Any attempt to refer to a volatile object through a non-volatile glvalue (e.g. through a reference or pointer to non-volatile type) results in undefined behavior.

Java 的标准原话等楼下补充
joshu
2023-02-01 12:24:59 +08:00
根据 cppref 上 atomic 章节的原话
除了 ms vc++的 volatile 是携带有部分原子语义的,其它的编译器你均不能认为有原子语义
另外,不要试图在 C 类语言上做自以为是的性能优化,C 的 atomic 库已经帮你在基于处理架构的优化了
普通写是否原子,和体系结构有关

java 不了解
mmdsun
2023-02-01 13:07:42 +08:00
楼主说的是什么语言?写 paper 还是?
深入的话参考这个论文:
http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.06.07c.pdf
b1ghawk
2023-02-01 18:35:33 +08:00
Re: volatile 写会在之前加上一个 StoreStore 屏障、在后面加上一个 StoreLoad 屏障。StoreLoad 的屏障不是代表禁止 volatile 写与后面可能有的 volatile 读和写重排序吗?

StoreLoad 是否有效存在两个充分条件:
1:后续指令是否是 volatile 读(决定是否需要 “插入” 或称 "执行" StoreLoad 屏障)。
2:架构是否存在 StoreLoad 重排(决定被执行的 StoreLoad 屏障是有效操作还是空操作)。
b1ghawk
2023-02-01 18:37:44 +08:00
另外 TSO + StoreLoad 差不多就是 SC 了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/912087

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX