日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

并发编程-06线程安全性之可见性 (synchronized + volatile)

發布時間:2025/3/21 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发编程-06线程安全性之可见性 (synchronized + volatile) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 線程安全性文章索引
  • 腦圖
  • 可見性定義
  • 導致不可見的原因
  • 可見性 -synchronized (既保證原子性又保證可見性)
  • 可見性 - volatile(但不保證操作的原子性)
    • volatile變量 寫操作
    • volatile變量 讀操作
  • 使用volatile嘗試解決計數并發錯誤的問題 【volatile無法解決該問題】
  • volatile使用場景
  • synchronized和volatile的比較
  • 代碼

線程安全性文章索引

并發編程-03線程安全性之原子性(Atomic包)及原理分析

并發編程-04線程安全性之原子性Atomic包的4種類型詳解

并發編程-05線程安全性之原子性【鎖之synchronized】

并發編程-06線程安全性之可見性 (synchronized + volatile)

并發編程-07線程安全性之有序性


腦圖


可見性定義

一個線程對共享變量值的修改,能夠及時的被其他線程看到。


導致不可見的原因

  • 線程交叉執行

  • 重排序結合線程交叉執行

  • 共享變量更新后的值沒有在工作內存與主內存之間及時更新

結合我們前面說過的Java內存模型,上述三個原因我們就很容易理解了。 不清楚的童鞋可以再回顧下 并發編程-02并發基礎CPU多級緩存和Java內存模型JMM


可見性 -synchronized (既保證原子性又保證可見性)

synchronized能夠實現原子性和可見性 。

JMM中關于Synchronized的規定

  • 線程解鎖前,必須把共享變量的最新值刷新到主內存
  • 線程加鎖時,必須將工作內存中的共享變量的值清空,從而使用共享變量時需要從主內存中重新讀取最新的值。【注意,加鎖和解鎖必須是同一把鎖

可見性 - volatile(但不保證操作的原子性)

volatile可以保證 可見性和 有序性

通過加入內存屏障禁止重排序優化來實現。

  • 對volatile變量寫操作時,會在寫操作后加入一條store屏障指令,將本地內存中的共享變量值刷新到主內存

  • 對volatile變量讀操作,會在讀操作前加入一條load指令屏障,從主內存中讀取共享變量

volatile本質是在告訴JVM當前變量在寄存器中的值是不確定的,使用前,需要先從主存中讀取,因此可以實現可見性。而對n=n+1,n++等操作時,volatile關鍵字將失效,不能起到像synchronized一樣的線程同步(原子性)的效果。


volatile變量 寫操作


volatile變量 讀操作


使用volatile嘗試解決計數并發錯誤的問題 【volatile無法解決該問題】


即使將count用volatile修飾,每次從主存中取到的都是最新的值,可是當多個線程同時取到最新的值,執行+1操作,當刷新到主存中的時候會覆蓋結果,從而丟失一些+1操作


volatile使用場景

  • 多線程中使用volatile變量,對變量的寫入操作不能依賴當前變量的值:如count++ .【 解釋下: count++不是原子操作,因為其可以分為:從主內存中讀取count的值,在自己線程的工作內存中將count的值+1,寫入最新的count的值到主內存。 對于count++,線程A和線程B都執行一次,最后輸出的count的值可能是1也可能是2】 。 比較適合 狀態標記 場景
  • 狀態標記偽代碼

    volatile boolean inited = false;// 線程A context = loadContext(); inited = true;// 線程B while(!inited ){sleep(); } doSomethingWithConfig(context);

    將inited 標記為 volatile , 當線程A更新inited后,因為是volatile,所以線程B可以及時從主內存中感知到inited的改變。 這樣就確保了線程B中使用的contex是初始化過的。

  • double check (比較常見的比如單例模式中的double check)

  • synchronized和volatile的比較

    • synchronized保證內存可見性和操作的原子性

    • volatile只能保證內存可見性

    • volatile不需要加鎖,比synchronized更輕量級,并不會阻塞線程

    • volatile標記的變量不會被編譯器優化,而synchronized標記的變量可以被編譯器優化(如編譯器重排序的優化).

    • volatile是變量修飾符,僅能用于變量,而synchronized是一個方法或塊的修飾符。


    代碼

    https://github.com/yangshangwei/ConcurrencyMaster

    總結

    以上是生活随笔為你收集整理的并发编程-06线程安全性之可见性 (synchronized + volatile)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。