簡體   English   中英

重新排序JMM之前發生的關系

[英]Reordering in happens-before relationship of JMM

它是JLS關於JMM之前發生的關系(第17.4.5節):

應該注意的是,兩個動作之間存在的先發生關系並不一定意味着它們必須在實現中以該順序發生。

我對這個聲明的例子很感興趣。

我理解這是正確的,作為一個例子可以是以下內容:

Thread 1

x = 1
lock M
y = 2                            
unlock M ----------------------->Thread 2:

                                 lock M
                                 z = 3
                                 w = 4
                                 unlock M

顯然,在這個執行跟蹤中,(x = 1)和(w = 4)之間存在一個先發生的關系:

(x = 1) happens-before (w = 4)

同樣在這種情況下(x = 1)在執行跟蹤中以(w = 4)排序。

Thread 1不使用變量w 因此,我們可以將它放在(x = 1)之前,而不違反Thread 1Thread 2的邏輯。

這是否意味着如果我們重新排序(x = 1)和(w = 4)然后發生 - 在這些語句之間的關系保留之前?

如果您有其他一些例子,請提供。

是的,你是對的,發生在獨立數據發生變化時,關系成立之前。 至於其他示例,請不要忘記發生之前 - 也適用於同一線程中的事件。 規則很簡單:

如果xy是同一個線程的動作,並且x在程序順序中出現在y之前,那么hb(x,y)

所以Java方法中的每個語句都發生在每個后面的語句之前,但當然JIT編譯器和CPU可以自由地重新排序獨立語句(並且它們實際上經常這樣做以優化性能)。 有時你可以從另一個沒有發生過的線程中觀察到這個重新排序 - 在與當前線程的關系之前。

線程1不使用變量w

您不能認為這是一個原因,因為實際上,Java內存模型沒有考慮在線程隔離的上下文中重新排序指令是否安全, 關於其他涉及線程的感知
沒有鎖定或內存屏障,JMM只保證在同一個線程中的語句之前發生。

在您的情況下,您在同一個對象(M)上有一個鎖定機制,因此發生“之前發生”。
Java中的synchronized (鎖定)或其他原子變量處理內存屏障原子性。 有關信息,構造函數中的volatile變量和final變量賦值僅處理內存障礙。

以這個例子為例,根本不處理任何內存障礙:

Class Reordering {
  int x = 0, y = 0;
  public void writer() {
    x = 1;
    y = 2;
  }

  public void reader() {
    int r1 = y;
    int r2 = x;
  }
} 

假設這個代碼同時在兩個線程中執行,並且y的讀取看到值2.因為這個寫入在寫入x之后,程序員可能會認為x的讀取必須看到值1.但是,寫入可能已被重新排序。 如果發生這種情況,則可能會發生對y的寫入,可能會讀取兩個變量,然后可能會發生對x的寫入。 結果是r1的值為2,但r2的值為0。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM