2011-07-09 38 views
3

我正在閱讀內存模型上的JLS規範17.4.5 Happens-before Order。 我不明白的第一條規則:瞭解JVM發生前 - 重新排序

「#如果X和Y是相同的線程和X的動作來在y之前在節目 順序,然後HB(X,Y)。」

假設A中的B是對象可在多個線程間共享(類對象的實例):

int i=A.getNum(); // ActionA 
int j=B.getNum(); // ActionB 

三個問題:

  1. 根據上述規則,這是否意味着hb(ActionA,ActionB)

  2. 如果對1的答案是真的,這是否意味着根據發生之前的規則,ActionB無法重新排序在遵循JSR133內存模型的任何JVM之前的ActionA之前?

  3. 如果1和2都是真的,ActionA和ActionB似乎不相關,爲什麼不能重新排列呢?只是爲了這個規範?

回答

8

這是我的理解是:

  1. 你說得對
  2. 他們可以重新排序,但前提是動作B處不依賴於動作A
結果

事前關係並沒有說明重新排序行爲。它只說如果HB(A,B)成立,那麼動作B必須看到動作A的記憶效應。

如果動作B不使用任何動作A的結果,那麼他們沒有理由不能重新排序。 (通常,「使用任何其他操作的結果」都非常廣泛,只能用於非常簡單的操作(如內存讀取/寫入),而不能用於使用外部資源(如I/O操作)的操作或基於時間的操作)

+0

謝謝大家,現在更清楚了 –

2

你的理解基本上是正確的。然而,要記住的關鍵是:

  • 重新排序時才允許不影響它的運行的線程的結果
  • 並不意味着重新排序允許其是否影響其他線程

正是這最後的事實是錯誤和困惑中的java多線程編程的常見原因。

3

是的,ActionA發生在ActionB之前。儘管如此,請閱讀該部分。這並不一定意味着JVM不能重新排序這些。這意味着ActionB必須觀察ActionA的效果,就是這樣。如果ActionB從不依賴於ActionA的效果,那麼這是非常正確的。