我正在閱讀線程和鎖的JLS文檔http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5。在多線程環境中讀取值
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
我很困惑上面的例子(ex no 17.5-1)在部分提到的如何f.y可以被視爲零。 Reader線程將讀取對象f爲null,在這種情況下,它不會執行任何操作,或者它將通過一些引用讀取對象f。如果對象f有引用,那麼構造函數必須已經完成其執行,即使多個Writer線程正在運行,以便可以將引用分配給f,並且如果構造函數已經執行,那麼fy應該被視爲4.
In什麼情況可以fy = 0是可能的?
感謝
這裏可能需要注意術語。對於大多數人來說:'編譯器'意味着'javac',並且該編譯器不會對任何東西重新排序。 JIT編譯器Hotspot可以重新排列指令。但即使如此,'編譯器'可能不是全部,因爲硬件(CPU)也可以執行指令重新排序。緩存行爲也可能導致重新排序指令。 –
好點的熱點編譯器@Martin。我編輯了我的答案。這是我的理解,CPU不做指令重新排序。它可能會傳輸指令,導致它們以不同的順序執行,但不能任意重新排序。 – Gray
是的,我認爲緩存行爲(以及可能的註冊使用)更可能像併發問題描述。 *一些*體系結構可以重新排列指令,但除非實際使用它們,否則這不是問題。 :) –