JMM中的因果關係似乎是最令人困惑的部分。我有幾個關於JMM因果關係的問題,並允許併發程序中的行爲。爲什麼在Java內存模型中允許這種行爲?
據我所知,目前的JMM總是禁止因果關係循環。 (對嗎?)現在
,按照該JSR-133文檔,24頁,圖16中,我們有一個例子:
最初x = y = 0
主題1:
r3 = x;
if (r3 == 0)
x = 42;
r1 = x;
y = r1;
線程2:
r2 = y;
x = r2;
直觀上,r1 = r2 = r3 = 42
似乎不可能。但是,它不僅被提及,而且在JMM中也是「允許的」。
對於可能性,從中我無法理解該文檔的解釋是:
編譯器可確定曾經分配給
x
值只有 0和42從這一點,編譯器可能推測,在我們執行r1 = x
的點 處,我們剛剛執行了42到x
的寫入,或者我們剛剛讀取了x
並看到了值42.在任何一種情況下,它都會合法讀取x
查看價值 42.然後它可以將r1 = x
更改爲r1 = 42
;這將允許y = r1
轉換爲y = 42
並且執行得更早,導致 有問題的行爲。在這種情況下,首先寫入y
承諾 。
我的問題是,究竟是什麼樣的編譯器優化? (我是編譯器無知的。)由於42僅僅是有條件地寫入的,所以當滿足if
語句時,編譯器如何決定去編寫x
?
其次,即使編譯器這個投機的優化,並承諾y = 42
和 然後最後使得r3 = 42
,是不是違反了因果循環的,因爲沒有原因,現在的效果區別剩下什麼?
實際上,在同一文件(第15頁,圖7)中有一個例子,其中提到了一個類似的因果迴路,因爲這是不可接受的。
那麼這個執行命令在JMM中怎麼合法呢?
@Alexei這解釋了一些。但是,編譯器不應該使用'r3 = 0'而不是'r3 = 42'嗎?或者他們只是在展示'一種可能性'! – gaganbm
編譯器不會生成'r3 = 42',它只會使'r3 = x'完好無損。編譯器優化並不總是以最大深度執行。如果優化可能違反正確性的可能性很小,則會被放棄。在給定的代碼中,不存在這樣的情況,但是如果存在其他代碼,則它們可以出現。另外,編譯器可以決定'r3 = 0'與'r3 = x'的價格相同。 –