我目前正在学习Java内存模型,以及它如何影响编译器可能进行的重新排序。但是,我对外部操作有点困惑。 JMM将它们定义为在操作之外可以观察到的动作。离开this question,我理解外部操作就像打印一个值,写入文件,网络操作等等。
现在,外部行动如何受到重新排序的影响?我认为很明显外部动作不能与另一个外部动作重新排序,因为这会改变程序的可观察行为(因此根据JMM不是有效的转换)。但是,如果使用正常的内存访问或同步操作重新排序外部操作呢?例如:
volatile int v = 5;
int x = v;
System.out.println("!");
可以在此打印并int x = v
重新排序吗?我看不到它改变行为,但是volatile v的读取与监视器获取相同,所以我不认为重新排序是有效的。
答案 0 :(得分:1)
外部操作以避免出现意外结果:
class ExternalAction {
int foo = 0;
void method() {
jni();
foo = 42;
}
native void jni(); /* {
assert foo == 0;
} */
}
假设实现了JNI方法以运行相同的断言,您不会期望这会失败。 JIT编译器无法确定任何外部的结果,因此JMM也禁止这样的重新排序。