1. 程式人生 > >《JAVA多執行緒程式設計的藝術》-volatile重排序規則理解

《JAVA多執行緒程式設計的藝術》-volatile重排序規則理解

1.volatile寫的記憶體語義如下:

  • 當寫一個volatile變數時,JMM會把該執行緒對應的本地記憶體中的共享變數重新整理到主記憶體。

2.volatile讀的記憶體語義如下:

  • 當讀一個volatile變數時,JMM會把該執行緒對應的本地記憶體置為無效。執行緒接下來將從主記憶體中讀取共享變數。

3.volatile重排序規則表如下:
是否能重排序 第二個操作
第一個操作 普通讀/寫 volatile讀 volatile寫
普通讀/寫 NO
volatile讀 NO NO NO
volatile寫 NO NO
  • 當第二個操作是volatile寫時,不管第一個操作是什麼,都不能重排序。這個規則確保volatile寫之前的操作不會被編譯器重排序到volatile寫之後。
  • 當第一個操作是volatile讀時,不管第二個操作是什麼,都不能重排序。這個規則確保volatile讀之後的操作不會被編譯器重排序到volatile讀之前。
  • 當第一個操作是volatile寫,第二個操作是volatile讀時,不能重排序。

以上內容從原書摘錄,原書並沒有解釋volatile重排序規則為什麼這樣,大概是這個規則很易理解,但對於我這個新手來說還是有些難度的,後來無意中將volatile的記憶體語義放在一塊思考,終於理解了這個規則,在此記下,方便日後觀看。

其實當這幾點放在一塊時,這個規則就很容易理解了,寫一個volatile時,會把執行緒對應的本地記憶體中共享變數重新整理到主記憶體(voaltile寫記憶體語義),這就對應著第二個操作是寫操作的規則,這裡為什麼不能重排序,因為重排序會導致volatile寫之前的操作排在後面,如果這時進行volatile寫操作就不能保證volatile寫之前的共享變數資料的一致,如此就違背了記憶體語義。

讀一個volatile,需要將本地記憶體置為無效,從主記憶體讀取共享變數(volatile讀記憶體語義),這條記憶體語義對應著第一個操作是volatile讀的規則,如果在這裡允許重排序,就會導致之前volatile讀後面的操作不能夠獲取到主記憶體中的共享資料,這樣也違背了記憶體語義。

第一個volatile寫,第二個volatile讀不能重排序,這個就不解釋了,可見性嘛。