本文的思想来源于:
Jeremy Manson and Brian Goetz, 《JSR 133 (Java Memory Model) FAQ》, February 2004, http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#synchronization
(1) 在一些情况下,对程序变量(对象实例变量、静态变量、数组元素)进行access的时候,会发现
access的执行顺序与程序中所指定的顺序并不一致。只要不改变程序的语义,编译器为了进行程
序的优化可以自由地reorder指令(instructions)。在运行期,处理器也可能以不同的顺序去执
行指令:数据可能会以不同于程序中所指定的顺序在处理器寄存器、处理器缓存以及住内存之间
移动。
(2) 下面举例说明:
Class Reordering {
int x = 0, y = 0;
public void writer() {
x = 1;
y = 2;
}
public void reader() {
int r1 = y;
int r2 = x;
}
}
假设有两个线程分别执行上面的示例程序代码中的writer和reader方法。在writer方法的程序中,
x被指定在y之前进行赋值。但是由于对y的赋值并不依赖于x的值,因此编译器可以reorder这些操
作。另外,执行writer线程的处理器也完全可以先将cache中y的值写回内存,然后再将x的值写回内存。
在两个操作的中间(y的值已经被写回内存,但是x的值尚未被写回内存的时候),执行reader方法
的线程得到的结果便是 r1 = y的真实值,但是 r2 = 0,而非x的真实值。
(3) 可能进行reorder的地方包括:编译器、JIT JVM、处理器缓存。
(4) Reorder的影响。在单线程的情况下,程序不必去关注指令的真实执行顺序,同时也不必在意
reordering的影响。然而,在多线程的情况下,如果程序没有被正确地synchronized,一个线程便
能够观测到reordering对其他线程的影响,即该线程可能会透明地看到其他线程的变量acess过程与
程序中specified不同。