為了實作volatile記憶體語義,JMM會分别限制編譯器重排序和處理器重排序
1.當第一個操作為普通的讀或寫時,如果第二個操作為volatile寫,則編譯器不能重排序這兩個操作(1,3)
2.當第一個操作是volatile讀時,不管第二個操作是什麼,都不能重排序。這個規則確定volatile讀之後的操作不會被編譯器重排序到volatile讀之前(第二行)
3.當第一個操作是volatile寫,第二個操作是volatile讀時,不能重排序(3,2)
4.當第二個操作是volatile寫時,不管第一個操作是什麼,都不能重排序(第三列)
為了實作volatile的記憶體語義,編譯器在生成位元組碼時,會在指令序列中插入記憶體屏障來禁止特定類型的處理器重排序。
JMM基于保守政策的JMM記憶體屏障插入政策:
1.在每個volatile寫操作的前面插入一個StoreStore屏障
2.在每個volatile寫操作的後面插入一個SotreLoad屏障
3.在每個volatile讀操作的後面插入一個LoadLoad屏障
4.在每個volatile讀操作的後面插入一個LoadStore屏障
上圖的StoreStore屏障可以保證在volatile寫之前,其前面的所有普通寫操作已經對任意處理器可見了
因為StoreStore屏障将保障上面所有的普通寫在volatile寫之前重新整理到主記憶體
x86處理器僅僅會對寫-讀操作做重排序
是以會省略掉讀-讀、讀-寫和寫-寫操作做重排序的記憶體屏障
在x86中,JMM僅需在volatile後面插入一個StoreLoad屏障即可正确實作volatile寫-讀的記憶體語義
這意味着在x86處理器中,volatile寫的開銷比volatile讀的大,因為StoreLoad屏障開銷比較大