是程序顺序'在Java中允许重新排序?

时间:2014-08-28 12:57:52

标签: java multithreading volatile jls

我有一个帖子

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是反映顺序的总顺序   这些动作将根据内线程执行   语义学。

看起来好像允许在这种情况下重新排序?

2 个答案:

答案 0 :(得分:1)

  

可以重新排序,所以我看到在第二个线程中读取了返回0吗?

不,如果你的断言是正确的,那就不行了,"这总是在我在线程1&#34中写出易失性标志后发生;

在线程2读取易失性标志之后,线程2在更新易失性a之前对线程1所做的最后一次更新将对线程2可见。

请参阅Brian Goetz的 Java Concurrency in Practice 第3.1.4节,以获取更详细的解释:http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601


但请注意!依赖于volatile变量的读写来同步其他变量可能被认为是不好的做法。问题是,volatile变量和其他变量之间的关系对于使用相同代码的其他程序员来说可能并不明显。

答案 1 :(得分:0)

如上所述here

  

旧的内存模型允许使用非易失性读写重新排序易失性写入,这与大多数开发人员对volatile的直觉不一致,因此引起混淆。

所以这种行为现在已经过时了(因为JSR-133已经引入并在Java 5.0中生效)。

其次,如here所述

  

按程序顺序链接在一起的操作并不排除"重新排序"