在Java中的併發實踐中,我們多次被告知,我們程序的指令可以由編譯器,JVM在運行時,甚至是處理器。所以我們應該假設執行的程序不會按照我們在源代碼中指定的順序執行完全相同的順序。java中的指令重新排序和發生之前的關係
然而,討論Java存儲器模型的最後一章提供了一個列表發生在之前的規則,指示JVM保留哪些指令排序。首先這些規則是:「程序順序規則主題中的每個動作,後來進來的程序以便線程的每一個動作之前發生」
我相信「程序順序」是指源代碼。
我的問題:假設這條規則,我想知道什麼指令可能實際上被重新排序。
「操作」被定義爲如下:
Java存儲模型的動作,其中包括讀取和寫入的變量,鎖和監視器的解鎖,以及啓動和有螺紋接合術語被指定。 JMM定義了在程序中的所有操作之前發生的部分排序。爲了保證執行動作B的線程可以看到動作A的結果(不管A和B是否出現在不同的線程中),在A和B之間的關係之前必定有一個事件發生。如果在兩個操作,JVM可以隨心所欲地對它們進行重新排序。 mentionned
其他順序規則是:
- 監視器鎖定規則。在同一監視器鎖上的每個後續鎖之前,都會發生監視器鎖的解鎖。
- 易變的變量規則。在每次後續讀取相同字段之前,對易失性字段進行寫入。
- 線程啓動規則。對線程的Thread.start調用發生在已啓動線程的每個操作之前。
- 線程終止規則。線程中的任何動作都會在任何其他線程檢測到線程已終止之前發生,要麼從Thread.join成功返回,要麼由Thread.isAlive返回false。
- 中斷規則。另一個線程上的線程調用中斷髮生在被中斷的線程檢測到中斷之前(通過拋出InterruptedException或調用isInterrupt或中斷)。
- 終結者規則。對象的構造函數的結束髮生在該對象的終結器開始之前。
- 傳遞性。如果A B之前發生,和B發生之前C,則A C.
謝謝。但是仍然缺少一些東西:如果程序順序規則真的存在,那麼無論「透視」(T1或T2)如何,y總是應該在T1之後的x後面賦值,不是嗎?因此T2應該總是顯示適當的x值。你提供的例子是明確的,我寧願討論程序順序規則本身的準確性(「線程中的每個動作發生在該線程中的每個動作之前,在程序順序中稍後進行」)。 – Martin 2013-05-21 11:14:58
@Martin的重點是_happens-before_只是一個部分順序 - 而'x = 5' _happens-before_'y = 6'由於程序順序規則,這兩者之間根本沒有_happens-before_關係指令和T2中發生的任何事情,所以T2可以看到'y = 6'的結果,而不是'x = 5'的結果。如果'y'是易變的,那麼在T1中'y = 6'和T2中'if(y == 6)'之間的關係會產生一個_happens-before_關係,這意味着_if_ T2會看到'y = 6' _then_ it還必須看到'x = 5'。 – 2013-05-21 11:56:40