1. 程式人生 > >java記憶體模型的happens-before語義順序問題?

java記憶體模型的happens-before語義順序問題?

java記憶體模型的happens-before語義順序問題?

注意,兩個操作之間具有 happens-before 關係,並不意味著前一個操作必須要在後一個操作之前執行!happens-before 僅僅要求前一個操作(執行的結果)對後 一個操作可見,且前一個操作按順序排在第二個操作之前(the first is visible to and ordered before the second)。happens- before 的定義很微妙,後文會具 體說明 happens-before 為什麼要這麼定義。

——引用自《深入理解JAVA記憶體模型》

這本書後邊有一個重排序的例子,說明沒有依賴關係的兩個語句可以重排,所以“並不意味著前一個操作必須要在後一個操作之前執行”。那“且前一個操作按順序排在第二個操作之前”這句話的含義又是什麼呢

黑色斜體兩段字所要表明的意思區別究竟在哪,感覺這兩句話是矛盾的呢?能否舉例說明一下

 

關注者

38

被瀏覽

2,012

關注問題寫回答

​邀請回答

​1 條評論

​分享

​舉報

收起

4 個回答

預設排序​

鍾懶

鍾懶

3 人贊同了該回答

It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal.

這是JSR133的原話。

就是說執行a1,a2這兩個操作,只要執行結果是跟順序執行a1,a2的執行結果一樣,就是合法的。比如write a = 1, write a = 2; read a;前兩個操作可以重排序,但讀操作不能和前兩個操作重排序。所以其實沒有矛盾的。

編輯於 2017-03-27

​贊同 3​​新增評論

​分享

​收藏​感謝

杜雙成

杜雙成

1 人贊同了該回答

Java記憶體模型中的happens-before是比較難理解的地方,為什麼要提出這樣的模型,這個牽制到計算機體系結構的一些知識,由於在計算機系統存在暫存器,L1,L2,L3 等多級快取,主儲存器,所以一個變數可能被儲存在計算機記憶體的不同區域,同時由於執行緒都對應一個稱為工作記憶體的區域,各個執行緒從記憶體總讀取變數在各自的工作記憶體中進行變數的操作,這樣就會出現變數不一致的情況,Java編譯器為了協調對變數的訪問,提出了自己的記憶體模型;happens-before的規則前後兩個操作滿足離散數學中的偏序關係, happens-before規則不是描述實際操作的先後順序,它是用來描述可見性的一種規則 ,也就是說在Java中常見的內建鎖synchronized等不僅是保持了同步,更是隱含著保持了記憶體的可見性,仔細想一想確實是這樣的;舉一個例子,happen-before中有一條規則稱為:在監視器上的解鎖操作必須是在同一個監視器的加鎖操作之前執行。 如果執行緒1解鎖了monitor a,接著執行緒2鎖定了a,那麼,執行緒1解鎖a之前的寫操作都對執行緒2可見(執行緒1和執行緒2可以是同一個執行緒)。 如果執行緒1寫入了volatile變數v(這裡和後續的“變數”都指的是物件的欄位、類欄位和陣列元素),接著執行緒2讀取了v,那麼,執行緒1寫入v及之前的寫操作都對執行緒2可見(執行緒1和執行緒2可以是同一個執行緒)。 ================》對於你疑問“ 並不意味著前一個操作必須要在後一個操作之前執行 ”,這裡說的先後是一種時間上先後,也就是說A操作在時間上先於B操作執行。但是按照happens-before中的8條規則,若不滿足其中的任何一條就無法確保兩個操作的可見性,編譯器將對指令進行重排序;後面的那句“ happens-before 僅僅要求前一個操作(執行的結果)對後 一個操作可見,且前一個操作按順序排在第二個操作之前 ”這句話的意思是在滿足happends-before的8條規則的前提下,在滿足可見性的條件下,編譯器允許對指令進行重新排序,這麼更加利於計算機cpu指令的執行,提升效能,但是在happends-before個約束下,滿足可見性,從而保證最終的結果保持一致性。最後我想說明的是,前面提到的偏序概念很重要,如果學過離散數學的話就不難理解了, happen-before關係是個偏序關係。兩個存在happen-before關係的操作不可能同時發生,一個操作A happen-before操作B,它們必定在時間上是完全錯開的,所以才有那句“ 且前一個操作按順序排在第二個操作之前 ”,這裡的先後不是時間上的先後,而是在happends-before約束下的先後,由於偏序關係要求必須錯開執行,不能同時,所以兩個操作必定是有順序的,所以。。。希望你能理解。

編輯於 2017-03-27

​贊同 1​​7 條評論

​分享

​收藏​感謝

wxweven

wxweven

攻城架構獅

我覺得必須要請出R大來詳細解釋下,以及編譯器如何做指令重排序的,坐等R大 

@RednaxelaFX

釋出於 2018-02-06