2016-03-04 131 views
16

我明白讀取獲取(不會對其後的讀取/寫入操作進行重新排序)和寫入釋放(不會對其前面的讀取/寫入操作進行重新排序)。 我的問題是: -Java易失性讀取刷新寫入和易失性寫入更新讀取

  1. 在讀取獲取的情況下,執行它之前的寫入刷新?
  2. 在寫入釋放的情況下,先前的讀取是否更新?

此外,是讀取獲取相同的易失性讀取,並釋放相同的易失性寫在Java中?

爲什麼這是重要的是,讓我們寫釋放的情況下..

y = x; // a read.. let's say x is 1 at this point 
System.out.println(y);// 1 printed 
//or you can also consider System.out.println(x); 
write_release_barrier(); 
//somewhere here, some thread sets x = 2 
ready = true;// this is volatile 
System.out.println(y);// or maybe, println(x).. what will be printed? 

在這一點上,爲x 2或1? 在這裏,考慮準備好變化。 據我所知,在易失性之前的所有商店將首先變得可見..然後只有易失性將變得可見。謝謝。

參考: - http://preshing.com/20120913/acquire-and-release-semantics/

回答

10

號:不是所有的寫操作都臉紅了,也不是所有的讀更新。

Java在多線程的「發生之前」基礎上工作。基本上,如果A發生在B之前,B發生在C之前,那麼A發生在C之前。因此,你的問題等於x=2正式發生 - 在某個讀取x的動作之前。

發生前邊緣基本上是通過與JLS 17.4.4中定義的關係同步建立的。有幾種不同的方式來做到這一點,但對於揮發物,它基本上相當於一個寫揮發發生,之前的讀取到同一揮發性:

  • 寫一個volatile變量v(§8.3 .1.4)同步 - 任何線程(其中「後續」根據同步順序定義)對v的所有後續讀取。

鑑於此,如果您的線程寫入ready = true,然後單獨寫並不意味着什麼之前發生它(只要是寫而言)。實際上恰恰相反;寫到ready發生在其他線程的事情之前,如果他們讀取ready

因此,如果其他線程(即設置x = 2)曾之後寫入準備它設置x = 2,並且此線程(你上面貼)然後ready,那就看x = 2。這是因爲在讀取之前寫入發生,並且讀取線程因此看到寫入線程已完成的所有內容(直到幷包括寫入)。否則,你有一場數據競賽,基本上所有的賭注都沒有了。

一對夫婦的其他注意事項:

  • 如果沒有之前發生邊緣,你可以仍然看到更新;這只是你不能保證。所以,不要假設,如果你沒有讀ready,那麼你仍然會看到x = 1。您可能會看到x = 1或x = 2,或者可能還有其他一些寫入(直到幷包括x = 0的默認值)
  • 在您的示例中,y始終爲1,因爲您不重新閱讀x之後的「某處here」評論。爲了達到這個答案,我假設在ready = true之前或之後有第二行y=x。如果不存在,那麼y的值將與第一個println中的值相同(假設沒有其他線程直接更改它 - 如果它是局部變量,則保證這一點),因爲線程內的動作總是顯示爲好像它們是不重新排序。
5

不,讀取volatile變量不會刷新前面的寫入。可見操作將確保前面的操作是可見的,但讀取volatile變量對其他線程不可見。

不,寫入volatile變量不會清除之前讀取的值的緩存。只保證刷新先前的寫入。

在你的例子中,在最後一行顯然y仍然是1。根據前面的輸出,對y只做了一項分配,這是1。也許這是一個錯字,你的意思是寫println(x),但即使如此,2的值也不能保證可見。

7

Java內存模型沒有用「read-acquire」和「write-release」來指定。這些術語/概念來自其他背景,並且由於您引用的文章非常清晰,它們經常被不同專家用來表示不同的東西。

如果您想了解Java中的揮發性物質是如何工作的,您需要了解Java存儲器模型和Java術語......這是(幸運的是)有根據且精確地指定了。試圖將Java的內存模型映射到「讀 - 獲取」和「寫釋放」語義是一個糟糕的主意,因爲:

  • 「讀 - 獲取」和「寫釋放」術語和語義並不好指定,並且

  • 一個假設的JMM->「read-acquire」/「write-release」語義映射只是JMM的一種可能的實現。其他映射可能存在,具有不同且同樣有效的語義


1 - ...那個專家已經注意到在JMM的某些版本中的缺陷模。但重要的是,已經做出了認真的嘗試來提供理論上合理的規範......作爲Java語言規範的一部分。