2011-07-12 34 views
2

Java存儲器模型提供了DRF保證(數據競爭自由),這意味着在寬鬆的java內存模型下執行時,數據競爭自由程序會產生與順序一致執行相同的行爲。我有以下問題: a)給定一個活潑的程序,編譯器(非常具體的任何jvm實現)做延遲集分析/線程轉義分析等,以找出需要插入的圍欄指令,使其競爭-自由?或者根據它在哪裏執行而做JIT? b)如果編譯器做了它(在這種情況下是jvm),爲什麼我們不能編寫racy程序,因爲編譯器無論如何都會將它轉換爲無競爭的程序?如果編譯器有辦法做到這一點(通過圍欄插入使它無競爭狀態),那麼如何編寫racy程序(故意),就像java中的一些併發數據結構的實現? c)第三種可能性是jvm本身不會將racy轉換爲無競賽節目,但存在其他分析可以爲我們做到這一點。是這樣嗎?通過JVM/JIT插入柵欄指令

回答

3

給定一個racy程序,編譯器(非常具體的任何jvm實現)做延遲集分析/線程轉義分析等,以找出需要插入的圍欄指令,使其無競爭?或者根據它在哪裏執行而做JIT?

內存圍欄指令特定於架構的指令集。它們不是JVM指令集中的等效指令。因此,JVM/JIT實際上向處理器發佈了fence指令。

如果編譯器這樣做(在這種情況下是jvm)爲什麼我們不能編寫racy程序,因爲編譯器無論如何都會將它轉換爲無競爭的程序?如果編譯器有辦法做到這一點(通過圍欄插入使它無競爭狀態),那麼如何編寫racy程序(故意),就像java中的一些併發數據結構的實現?

編譯器只會確保當它生成字節碼時,對JVM中的變量執行的所有操作都遵守Java內存模型中指定的規則。具體而言,在優化領域,編譯器可以自由地優化任何指令集,只要它不影響動作之間必須存在的發生之前的關係或動作之間的同步順序。例如,編譯器不會重新組織對易失性變量的讀寫操作。它還將確保在進入或離開守護(同步)的代碼區域時不會違反關係。

因此,編譯器將「racy」程序轉換爲無競爭程序的說法不正確。事實上,一個假定無競爭的程序(但不是在Java內存模型下)可能會在優化之後變成「活潑」的程序。

Java中數據結構的併發實現依賴於Java存儲模型提供的保證。具體而言,這是來自Java 5的修訂後的Java內存模型,其中準確指定了易失性變量的讀取和寫入之間的事前關係。 java.util.concurrent包中的ConcurrentXXX類在很大程度上依賴於volatile讀取的承諾行爲,以確保無競爭行爲。在Java內存模型下,如果這是程序順序,則在讀取之前保證寫入volatile變量;簡而言之,易失性讀取將始終檢索變量中最準確的數據版本。併發類利用它來確保數據結構可以被單個線程更新,同時被多個其他線程(在任何其他場景中,將會有競爭條件)讀取。

或者第三種可能性是jvm本身不會將racy轉換爲免競爭程序,但存在可以爲我們做的其他分析。是這樣嗎?

JVM發出內存圍欄指令。它不會執行任何「racy」程序轉換爲「無race」程序。如果編譯器生成的字節碼服從Java存儲器模型,那麼JVM/JIT將在必要時發出存儲器圍欄指令 - 讀取/寫入易失性變量,獲取或釋放對象上的監視器等。

如果存在重複我自己,JVM和編譯器都不會將「活潑」的程序轉換爲無競爭的程序,反之亦然。任何相反的行爲都是Java內存模型或JVM中的錯誤。您將需要通過理解程序順序,同步順序和發生順序來編寫程序作爲無競爭的程序,並且編譯器和JVM將確保在運行時確保它。

我想鼓勵您閱讀this article at InfoQ,以獲取有關JVM如何發出內存隔離指令並確保Java內存模型所做承諾的更多詳細信息。