易失性写入与非易失性写入重排

4
volatile写操作是否会与非volatile写操作重新排序?
例如: 我有两个线程T1和T2: T1:
i = 10;  
volatile boolean result = true;

T2:

while(!result){
}

System.out.println(i);

T2是否总是看到i(10)的更新值,还是旧值?

在Java中,你不能做 Volatile int boolean result = true; - BackSlash
JLS中相关的部分是[17.4.2](http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.2),其中volatile写和读被列为同步操作。因此,必须打印10。 - kiheru
2个回答

2
是的。对于一个volatile语句,存在happens-before关系:
请考虑这个stackoverflow问题:Java中的volatile变量在读取之前会强制实施happens-before关系吗? 一个对volatile字段的写操作 happens-before 后续对同一字段的每次读操作。对volatile字段的写和读具有类似于进入和退出监视器的内存一致性效果,但不涉及互斥锁定。此外,您可以阅读名为“Java并发实战”的杰出著作中的第3.1.3节(锁定和可见性)。那里有一个相关解释,涉及类似的可见性问题,大纲如下:
锁定不仅是关于互斥的;它也关乎内存可见性。为了确保所有线程看到共享可变变量的最新值,读写线程必须在公共锁上进行同步
在您的代码中,锁是volatile变量。

1
据我所了解,这是正确同步的,因此不会出现竞争情况,并且始终打印10。
重要的部分是,在线程内,事情按程序顺序发生,并且对易失变量的写入发生在看到该值的读取之前。结合传递闭包规则,这意味着对i的赋值发生在打印语句之前。 i = 10发生在result = true之前。result = true发生在线程2中将result读取为true之前。result被读取为true发生在System.out.println(i);之前。因此,i = 10发生在System.out.println(i);之前。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接