【问题标题】:Is 'program order' in Java allows reordering?Java中的“程序顺序”是否允许重新排序?
【发布时间】:2014-08-28 12:57:51
【问题描述】:
在一个线程中我有
write a = 0
write a = 1
write volatile flag = 1
在第二个线程中我有
read volatile flag // This always happens after I write volatile flag in thread 1
read a
是否会发生重新排序,所以我看到 read a 在第二个线程中返回 0?
如果不是,请有人详细解释原因吗?
我问是因为我对 JLS 的这个定义感到困惑:
在每个线程 t 执行的所有线程间动作中,
t 的程序顺序是一个总顺序,它反映了其中的顺序
这些动作将根据线程内执行
t的语义。
在这种情况下似乎允许重新排序?
【问题讨论】:
标签:
java
multithreading
volatile
jls
【解决方案1】:
是否可以重新排序,以便我看到在第二个线程中读取到返回 0?
不,如果你的断言是正确的,“这总是发生在我在线程 1 中写入 volatile 标志之后”
线程 1 在更新 volatile flag 之前对变量 a 所做的最后一次更新将在线程 2 读取 volatile 标志后对线程 2 可见。
请参阅 Brian Goetz 的 Java Concurrency in Practice 的第 3.1.4 节以获得更详细的解释:http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601
但请注意!依赖 volatile 变量的读写来同步 other 变量可能被认为是一种不好的做法。问题是,volatile 变量和其他变量之间的关系对于使用相同代码的其他程序员来说可能并不明显。
【解决方案2】:
正如here所说的
旧的内存模型允许 volatile 写入与 nonvolatile 读取和写入重新排序,这与大多数开发人员对 volatile 的直觉不一致,因此会造成混乱。
所以这种行为现在已经过时了(因为 JSR-133 被引入并在 Java 5.0 中生效)。
其次,正如here所说的
按程序顺序链接在一起的动作不排除被“重新排序”