Java多線程之記憶體可見度

來源:互聯網
上載者:User

標籤:共用變數   可見度   synchronized   java多線程   volatile   

一、JAVA記憶體模型簡介

JAVA Merory  Model描述了JAVA程式中各種變數(線程共用變數)的訪問規則,以及在JVM中將變數儲存到記憶體和從記憶體中讀取變數這樣的底層細節。

所有的變數都儲存在主記憶體中,但是每個線程都有自己的獨立工作記憶體,儲存該線程使用到的變數的一個副本。


兩條規定

1.線程對共用變數的操作只能在獨立的工作記憶體中進行,不能在主記憶體中直接讀寫;

2.不同線程之間無法直接存取其他線程的工作記憶體中的變數,需要通過主記憶體完成。

實現共用變數的可見度,必須保證兩點

1.線程修改後的共用變數能及時從工作記憶體重新整理到主記憶體中;

2.其他線程能及時把共用變數的最新值從主記憶體中更新到工作記憶體中。

JAVA從語言層面支援的可見度實現方式

synchronized; volatile


二、synchronized實現可見度
synchronized除了使代碼同時只能被一個線程執行的功能,還有一個功能就是實現可見度。
關於synchronized的兩條規定1.線程解鎖前,必須把共用變數的最新值刷到主記憶體去;2.線程加鎖時,清空工作記憶體的共用變數值,從主記憶體中重新讀取。 這兩條規定保證了線程在解鎖前對共用變數的操作在下次加鎖前對其他線程可見。
synchronized實現可見度的過程
1.獲得互斥鎖2.清空工作記憶體3.從主記憶體中拷貝共用變數的最新值到工作記憶體4.執行代碼5.把修改後的變數值更新到主記憶體6.釋放鎖
as-if-serial與重排序重排序: 代碼的執行順序和書寫順序不相同,指令重排序是編譯器或處理器為了提高效能而做的最佳化。分為 編譯器最佳化、處理器指令級並行重排序、記憶體系統的重排序(對讀寫緩衝的最佳化,如上所說的那些)


as-if-serial:
無論如何重排序,程式執行的結果與代碼順序執行的結果相一致。(這並不是說就不進行重排序了!)

Java在單線程下是保證as-if-serial的。


導致共用變數線上程間不可見的原因及解決方案1.線程交叉執行;  synchronized的原子性解決這個問題2.重排序+線程交叉執行(甚至if() 與 {}中都可能被重排序,控制依賴關係並不是重排序的約束,只有資料依賴關係才是) synchronized的原子性解決這個問題3.共用變數更新後的值沒有在主記憶體與工作記憶體之間及時更新 synchronized的兩條規定解決這個問題

三、volatile實現可見度
volatile關鍵字可以保證volatile變數的可見度,但是不能保證volatile變數複合操作的原子性。
volatile如何?通過加入記憶體屏障和禁止指令重排序來實現:
對volatile變數執行寫操作時,會在寫操作後加一條store屏障指令,會把CPU寫緩衝的緩衝強制重新整理到主記憶體,還能防止處理器把volatile前的變數重排序到volatile之後。對volatile變數執行讀操作時,會在讀操作前加一條load屏障指令。在讀取時強制從主記憶體中讀取。
通俗的說,就是volatile變數每次被線程訪問時,都強制從主記憶體中重讀該變數的值,而不是從工作記憶體的緩衝中;當該值發生變化時,強制線程把最新的值重新整理到主記憶體中。
不能保證volatile變數複合操作的原子性比如 :private  volatile int a=0;a++;   //不是原子操作:分三步, 讀取a的值,a+1;寫回a的值
但是下面的是原子操作:synchronized(this){a++;}
除了synchronized之外,還可以用Lock:Lock lock= new ReentrantLock();  //可重新進入鎖然後在後面:lock.lock();try{a++;}finally{lock.unlock();}
volatile的適用情境1.對變數的寫入操作不依賴當前值   不滿足: num++; num=num*5 ...   滿足:    布爾變數等等2.該變數沒有包含在具有其他變數的不變式中   即程式中有多個volatile變數時,各自要獨立。如a,b;  如果有a<b這樣的式子,就不滿足。
所以volatie的適用範圍不如synchronized大。
四、synchronized與volatile的比較
1.volatile不需要加鎖,比synchronized輕量級,不會造成線程阻塞。2.synchronized既可以保證可見度,又可以保證原子性;而volatile只能保證可見度。


===========================================================================(文章是看完慕課的視頻後寫的,感謝 http://www.imooc.com/view/352)
轉載請註明出處,謝謝!

Java多線程之記憶體可見度

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.