volatile和final

1、關於內存屏障:(摘自內存屏障

(1)LoadLoad屏障:對於這樣的語句Load1; LoadLoad; Load2,在Load2及後續讀取操作要讀取的數據被訪問前,保證Load1要讀取的數據被讀取完畢。

(2)StoreStore屏障:對於這樣的語句Store1; StoreStore; Store2,在Store2及後續寫入操作執行前,保證Store1的寫入操作對其它處理器可見。

(3)LoadStore屏障:對於這樣的語句Load1; LoadStore; Store2,在Store2及後續寫入操作被刷出前,保證Load1要讀取的數據被讀取完畢。

(4)StoreLoad屏障:對於這樣的語句Store1; StoreLoad; Load2,在Load2及後續所有讀取操作執行前,保證Store1的寫入對所有處理器可見。

2、volatile內存屏障(摘自Java併發專題【5】徹底理解volatile
(1)在每個volatile寫操作的前面插入一個StoreStore屏障;
(2)在每個volatile寫操作的後面插入一個StoreLoad屏障;
(3)在每個volatile讀操作的後面插入一個LoadLoad屏障;
(4)在每個volatile讀操作的後面插入一個LoadStore屏障。


3、final域重排序規則(摘自Java併發專題【6】你真的瞭解final嗎?

(1)寫final域的重排序規則

    禁止對final域的寫重排序到構造函數之外,這個規則的實現主要包含了兩個方面:

  • JMM禁止編譯器把final域的寫重排序到構造函數之外;

  • 編譯器會在final域寫之後,構造函數return之前,插入一個storestore屏障(關於內存屏障可以看這篇文章)。這個屏障可以禁止處理器把final域的寫重排序到構造函數之外。

(2)讀final域重排序規則

 在一個線程中,初次讀對象引用和初次讀該對象包含的final域,JMM會禁止這兩個操作的重排序。(注意,這個規則僅僅是針對處理器),處理器會在讀final域操作的前面插入一個LoadLoad屏障

    實際上,讀對象的引用和讀該對象的final域存在間接依賴性,一般處理器不會重排序這兩個操作。但是有一些處理器會重排序,因此,這條禁止重排序規則就是針對這些處理器而設定的。

(3)針對引用數據類型,final域寫針對編譯器和處理器重排序增加了這樣的約束:在構造函數內對一個final修飾的對象的成員域的寫入,與隨後在構造函數之外把這個被構造的對象的引用賦給一個引用變量,這兩個操作是不能被重排序的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章