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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

volatile 手摸手带你解析

發布時間:2025/3/20 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 volatile 手摸手带你解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方?好好學java?,選擇?星標?公眾號

重磅資訊、干貨,第一時間送達 今日推薦:終于放棄了單調的swagger-ui了,選擇了這款神器—knife4j個人原創100W+訪問量博客:點擊前往,查看更多

前言

volatile 是 Java 里的一個重要的指令,它是由 Java 虛擬機里提供的一個輕量級的同步機制。一個共享變量聲明為 volatile 后,特別是在多線程操作時,正確使用 volatile 變量,就要掌握好其原理。

特性

volatile 具有可見性有序性的特性,同時,對 volatile 修飾的變量進行單個讀寫操作是具有原子性。

這幾個特性到底是什么意思呢?

  • 可見性:?當一個線程更新了 volatile 修飾的共享變量,那么任意其他線程都能知道這個變量最后修改的值。簡單的說,就是多線程運行時,一個線程修改 volatile 共享變量后,其他線程獲取值時,一定都是這個修改后的值。

  • 有序性:?一個線程中的操作,相對于自身,都是有序的,Java 內存模型會限制編譯器重排序和處理器重排序。意思就會說 volatile 內存語義單個線程中是串行的語義。

  • 原子性:?多線程操作中,非復合操作單個 volatile 的讀寫是具有原子性的。

可見性

可見性是在多線程中保證共享變量的數據有效,接下來我們通過有 volatile 修飾的變量和無 volatile 修飾的變量代碼的執行結果來做對比分析。

附上我歷時三個月總結的?Java面試思維導圖,拿去不謝!

下載方式

1.?首先掃描下方二維碼

2.?后臺回復「思維導圖」即可獲取

無 volatile 修飾變量

以下是沒有 volatile 修飾變量代碼,通過創建兩個線程,來驗證 flag 被其中一個線程修改后的執行情況。

/** * Created by YANGTAO on 2020/3/15 0015. */public class ValatileDemo {static Boolean flag = true;public static void main(String[] args) {// A 線程,判斷其他線程修改 flag 之后,數據是否對本線程有效 new Thread(() -> { while (flag) {} System.out.printf("********** %s 線程執行結束!**********", Thread.currentThread().getName()); }, "A").start();// B 線程,修改 flag 值 new Thread(() -> { try { // 避免 B 線程比 A 線程先運行修改 flag 值 TimeUnit.SECONDS.sleep(1); flag = false; // 如果 flag 值修改后,讓 B 線程先打印信息 TimeUnit.SECONDS.sleep(2);System.out.printf("********** %s 線程執行結束!**********", Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } }, "B").start();}}

上面代碼中,當 flag 初始值 true,被 B 線程修改為 false。如果修改后的值對 A 線程有效,那么正常情況下 A 線程會先于 B 線程結束。執行結果如下:

執行結果是:當 B 線程執行結束后, flag=false并未對 A 線程生效,A 線程死循環。

volatile 修飾變量

在上述代碼中,當我們把 flag 使用 volatile 修飾:

/** * Created by YANGTAO on 2020/3/15 0015. */public class ValatileDemo {static volatile Boolean flag = true;public static void main(String[] args) {// A 線程,判斷其他線程修改 flag 之后,數據是否對本線程有效 new Thread(() -> { while (flag) {} System.out.printf("********** %s 線程執行結束!**********", Thread.currentThread().getName()); }, "A").start();// B 線程,修改 flag 值 new Thread(() -> { try { // 避免 B 線程比 A 線程先運行修改 flag 值 TimeUnit.SECONDS.sleep(1); flag = false; // 如果 flag 值修改后,讓 B 線程先打印信息 TimeUnit.SECONDS.sleep(2);System.out.printf("********** %s 線程執行結束!**********", Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } }, "B").start();}}

B 線程修改 flag 值后,對 A 線程數據有效,A 線程跳出循環,執行完成。所以 volatile 修飾的變量,有新值寫入后,對其他線程來說,數據是有效的,能被其他線程讀到。

主內存和工作內存

上面代碼中的變量加了 volatile 修飾,為什么就能被其他線程讀取到,這就涉及到 Java 內存模型規定的變量訪問規則。

  • 主內存:主內存是機器硬件的內存,主要對應Java 堆中的對象實例數據部分。

  • 工作內存:每個線程都有自己的工作內存,對應虛擬機棧中的部分區域,線程對變量的讀/寫操作都必須在工作內存中進行,不能直接讀寫主內存的變量。

上面 無volatile修飾變量部分的代碼執行示意圖如下:

當 A 線程讀取到 flag 的初始值為 true,進行 while 循環操作,B 線程將工作內存 B 里的 flag 更新為 false,然后將值發送到主內存進行更新。隨后,由于此時的 A 線程不會主動刷新主內存中的值到工作內存 A 中,所以線程 A 所取得 flag 值一直都是 true,A 線程也就為死循環不會停止下來。

上面 volatile修飾變量部分的代碼執行示意圖如下:

當 B 線程更新 volatile 修飾的變量時,會向 A 線程通過線程之間的通信發送通知(JDK5 或更高版本),并且將工作內存 B 中更新的值同步到主內存中。A 線程接收到通知后,不會再讀取工作內存 A 中的值,會將主內存的變量通過主內存和工作內存之間的交互協議,拷貝到工作內存 A 中,這時讀取的值就是線程 A 更新后的值 flag=false。整個變量值得傳遞過程中,線程之間不能直接訪問自身以外的工作內存,必須通過主內存作為中轉站傳遞變量值。在這傳遞過程中是存在拷貝操作的,但是對象的引用,虛擬機不會整個對象進行拷貝,會存在線程訪問的字段拷貝。

有序性

volatile 包含禁止指令重排的語義,Java 內存模型會限制編譯器重排序和處理器重排序,簡而言之就是單個線程內表現為串行語義。那什么是重排序?重排序的目的是編譯器和處理器為了優化程序性能而對指令序列進行重排序,但在單線程和單處理器中,重排序不會改變有數據依賴關系的兩個操作順序。比如:

/** * Created by YANGTAO on 2020/3/15 0015. */public class ReorderDemo { static int a = 0;static int b = 0;public static void main(String[] args) { a = 2; b = 3; }} // 重排序后: public class ReorderDemo { static int a = 0;static int b = 0;public static void main(String[] args) { b = 3; // a 和 b 重排序后,調換了位置 a = 2; }}

但是如果在單核處理器和單線程中數據之間存在依賴關系則不會進行重排序,比如:

/** * Created by YANGTAO on 2020/3/15 0015. */public class ReorderDemo {static int a = 0;static int b = 0;public static void main(String[] args) { a = 2; b = a; }} // 由于 a 和 b 存在數據依賴關系,則不會進行重排序

volatile 實現特有的內存語義,Java 內存模型定義以下規則(表格中的 No 代表不可以重排序):

Java 內存模型在指令序列中插入內存屏障來處理 volatile 重排序規則,策略如下:

  • volatile 寫操作前插入一個 StoreStore 屏障

  • volatile 寫操作后插入一個 StoreLoad 屏障

  • volatile 讀操作后插入一個 LoadLoad 屏障

  • volatile 讀操作后插入一個 LoadStore 屏障

該四種屏障意義:

  • StoreStore:在該屏障后的寫操作執行之前,保證該屏障前的寫操作已刷新到主內存。

  • StoreLoad:在該屏障后的讀取操作執行之前,保證該屏障前的寫操作已刷新到主內存。

  • LoadLoad:在該屏障后的讀取操作執行之前,保證該屏障前的讀操作已讀取完畢。

  • LoadStore:在該屏障后的寫操作執行之前,保證該屏障前的讀操作已讀取完畢。

原子性

前面有提到 volatile 的原子性是相對于單個 volatile 變量的讀/寫具有,比如下面代碼:

/** * Created by YANGTAO on 2020/3/15 0015. */public class AtomicDemo {static volatile int num = 0;public static void main(String[] args) throws InterruptedException {final CountDownLatch latch = new CountDownLatch(10); for (int i = 0; i < 10; i++) { // 創建 10 個線程 new Thread(() -> { for (int j = 0; j < 1000; j++) { // 每個線程累加 1000 num ++; } latch.countDown(); }, String.valueOf(i+1)).start(); }latch.await(); // 所有線程累加計算的數據 System.out.printf("num: %d", num); }}

上面代碼中,如果 volatile 修飾 num,在 num++ 運算中能持有原子性,那么根據以上數量的累加,最后應該是 num:10000。代碼執行結果:

結果與我們預計數據的相差挺多,雖然 volatile 變量在更新值的時候回通知其他線程刷新主內存中最新數據,但這只能保證其基本類型變量讀/寫的原子操作(如:num = 2)。由于 num++是屬于一個非原子操作的復合操作,所以不能保證其原子性。

使用場景

  • volatile 變量最后的運算結果不依賴變量的當前值,也就是前面提到的直接賦值變量的原子操作,比如:保存數據遍歷的特定條件的一個值。

  • 可以進行狀態標記,比如:是否初始化,是否停止等等。

  • 總結

    volatile 是一個簡單又輕量級的同步機制,但在使用過程中,局限性比較大,要想使用好它,必須了解其原理及本質,所以在使用過程中遇到的問題,相比于其他同步機制來說,更容易出現問題。但使用好 volatile,在某些解決問題上能獲取更佳的性能。

    最后,再附上我歷時三個月總結的?Java 面試 + Java 后端技術學習指南,這是本人這幾年及春招的總結,目前,已經拿到了大廠offer,拿去不謝!

    下載方式

    1.?首先掃描下方二維碼

    2.?后臺回復「Java面試」即可獲取

    總結

    以上是生活随笔為你收集整理的volatile 手摸手带你解析的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 激情瑟瑟 | 按摩ⅹxxx性hd中国 | 国产免费又爽又色又粗视频 | 一本色道无码道dvd在线观看 | 麻豆影视免费观看 | 一本久久精品一区二区 | 午夜在线网站 | 亚洲精品国产日韩 | 麻豆一区二区三区精品视频 | 日本精品黄| 91精品国产综合久久福利软件 | 国产后入清纯学生妹 | 色婷婷av久久久久久久 | 日韩在线三区 | 色撸撸在线 | 亚洲一本在线观看 | 亚洲av少妇一区二区在线观看 | www.av麻豆 | 手机av资源 | 在线色网站 | 一级黄片毛片 | 无码熟妇人妻av | 国产在线一区二区视频 | 高清一区二区视频 | 卡通动漫精品一区二区三区 | 大尺度摸揉捏胸床戏视频 | www.超碰在线.com | 精品韩国一区二区三区 | 无码人妻精品一区二区50 | 久久性av| 青青草97国产精品麻豆 | 蜜桃精品在线观看 | 中文字幕在线观看 | 亚洲精品成人影视 | 99热这里只有精品5 国产精品伦子伦免费视频 精品一二三 | 91精品国产自产精品男人的天堂 | 免费久草视频 | 九一av | 香蕉视频黄色在线观看 | av免费国产 | 天天视频国产 | 色婷婷基地 | av大全网站 | 中文字幕无码人妻少妇免费 | av丝袜天堂 | 亚洲图片小说区 | 波多野结衣爱爱 | 亚洲伦理久久 | 色综合99久久久无码国产精品 | 国产aⅴ | 沈樵精品国产成av片 | av中文资源在线 | 伊人色在线视频 | 女子spa高潮呻吟抽搐 | 小色瓷导航 | 影音先锋男人资源网站 | 久久久久亚洲精品国产 | 亚洲第一欧美 | av女优天堂在线观看 | 2020狠狠干 | 在线小视频 | 国产原创视频 | 国产一级片自拍 | 国产又粗又猛又黄又爽 | 亚洲一级片av | 国产又黄又骚 | 国产性―交一乱―色―情人 | 男人和女人搞鸡 | 久久99精品久久久久久水蜜桃 | 91搞| 成人国产精品久久久网站 | 日韩欧美一二区 | 在线观看欧美亚洲 | 国产综合在线观看 | 麻豆自拍偷拍 | 国产片天天弄 | 无码人妻精品一区二 | 欧美另类xxxx野战 | 亚洲一区二区高清视频 | 女人黄色片| 在线观看免费中文字幕 | 在线爱情大片免费观看大全 | 在线观看免费 | a毛片基地 | 久久久久久黄色 | 国产精品乱子伦 | 日韩免费黄色 | 好吊色一区二区三区 | 国产精品久久综合视频 | 国产a级大片 | 一区二区成人免费视频 | 久久人久久 | 国产精品日日做人人爱 | 亚洲毛片a | 伊人成人在线视频 | 特及毛片 | 欧美你懂得 | 黄色片a级片 | 麻豆精品免费 |