多線程之記憶體可見度

來源:互聯網
上載者:User

標籤:mic   serial   ++   副本   其他   get   多個   關鍵字   int   

可見度的概念

一個線程對共用變數值的修改,能夠及時地被其他線程看到

共用變數值:如果一個變數在多個線程的工作記憶體中都使用,存在副本,那麼這個變數就是這幾個線程的共用變數

兩條重要規定:
  1. 線程對共用變數的所有操作都必須在自己的工作記憶體中進行,不能直接從主記憶體中讀寫
  2. 不同線程之間無法直接存取其他線程工作記憶體中的變數,線程間變數值得傳遞需要通過主記憶體來完成
JMM(Java Memory Model)
  1. 所有的變數都儲存在主記憶體中
  2. 每個線程都有自己獨立的工作記憶體,裡面儲存該線程使用到的變數的副本(主記憶體中該變數的一份拷貝)
共用變數可見度實現原理

線程1把工作記憶體1中更新過的共用變數重新整理到主記憶體中,主記憶體把最新的共用變數的值更新到工作記憶體2中,線程2就能及時看到線程1的修改

synchronize實現可見度
  1. JMM關於synchronize的兩條規定

    線程解鎖前,必須把共用變數的最新值重新整理到主記憶體中
    線程加鎖是,將清空工作記憶體中共用變數的值,從而使用共用記憶體時,需要從主記憶體中重新讀取最新的值(加鎖和解鎖需要同一把鎖)

  2. 重排序 as-if-serial
volatile實現可見度
  1. volatile關鍵字:

    能夠保證volatile變數的可見度
    不能保證volatile變數複合操作的原子性

  2. volatile如何?記憶體可見度

    通過加入記憶體屏障和禁止重排序最佳化來實現
    對變數執行寫操作時,會在寫操作後加入一條store屏障指令
    volatile 變數執行度操作時,會在讀操作前加入一條load屏障指令

  3. volatile不能保證原子性

    當a線程的工作變數已經讀過變數的值後,即使b線程改變變數的值,並store到記憶體中,也不會觸發a線程load,因為a線程讀取時已經load過了。

  4. 保證變數自增操作的原子性

    使用synchronize關鍵字
    使用ReentrantLock(java.until.concurrent.locks)
    使用AtomicInterger
    (vava.util.concurrent.atomic)

  5. volatile適用場合
    同時滿足:
  • 對變數的寫入操作不依賴其當前值,

    不滿足:number++,count=count*5等
    滿足:boolean變數,記錄溫度變化的變數等

  • 該變數沒有包含在具有其他變數的不變式中

    不滿足:不變式low<up

final也可以保證記憶體可見度synchronize 和 volatile 比較

volatile不需要加鎖,不會阻塞線程
從記憶體可見度角度講volatile讀相當於加鎖,volatile寫相當於解鎖
synchronize既可以保證可見度和原子性

coding個人部落格連結

參考資料-視頻

多線程之記憶體可見度

聯繫我們

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