附2 volatile,volatile

來源:互聯網
上載者:User

附2 volatile,volatile

註:在閱讀本章之前,先要瞭解Java記憶體模型,見上一章《附1 Java記憶體模型與共用變數可見度》,連結如下:

http://www.cnblogs.com/java-zhao/p/5124725.html

1、volatile用法

具體的用法可以參照《第二章 ConcurrentHashMap源碼解析》中的Segment內部類的count屬性,可以看看多線程情況下怎樣對其進行操作的,具體連結如下;

http://www.cnblogs.com/java-zhao/p/5113317.html

或者可以參照《第三章 CopyOnWriteArrayList源碼解析》中CopyOnWriteArrayList的底層數組,具體連結如下;

http://www.cnblogs.com/java-zhao/p/5121944.html

 

2、具體的實現原理

  • 對volatile變數執行寫操作時,會在寫操作後加入一條store屏障指令
  • 對volatile變數執行讀操作時,會在讀操作前加入一條load屏障指令

說人話:

  • 對volatile變數執行讀操作時,都要強制的先從主記憶體讀取最新的變數值到工作記憶體,然後再讀工作記憶體中所儲存的變數副本
  • 對volatile變數執行寫操作時,又會強制的將工作記憶體中的剛剛改變的值寫到主記憶體中去

通過上邊這樣模式,每個線程拿到的volatile變數值都是最新的。

注意:

volatile無法實現原子性:

eg.

private volatile int count = 0;

假設現在有兩條線程分別對count執行加1操作,那麼期待的結果最後count==2,但是看下邊的分析:

假設有如下流程:

1)線程a擷取了count==0;

2)線程b擷取了count==0;

3)線程b對count+1,之後寫入主記憶體count==1;

4)線程a對count+1,之後寫入主記憶體count==1;

結果count==1而非count==2,原因就是線程a擷取count後,volatile不能實現原子性,這個時候b也能去操作count。

想要實現原子性,使用synchronized去鎖住增加方法,或者使用ReentrantLock去鎖住增加代碼;當然,以上情境使用AtomicInteger更好。

 

3、volatile使用情境

  • 運算結果並不依賴當前值,例如Boolean就可,而number++這樣的就不行
  • 運算結果依賴當前值但是能夠確保只有單一線程修改變數的值,例如ConcurrentHashMap中Segment的count變數
  • 變數不需要與其他的狀態變數共同參與不變約束,例如low<up這樣的情境就不行

 

註:

  • 關於volatile禁止指令重排序的介紹去看《深入理解Java虛擬機器(第二版)》第十二章"Java記憶體模型與線程"
  • 通常情況下,能用volatile解決的就不去用synchronized了

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.