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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量”

發布時間:2023/12/20 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量” 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1. 面試官:“請談談你對volatile的理解”

2. 面試官接著問:“既然volatile不能保證原子性,那工作中如何解決這個問題呢?”

3. 官試官:“volatile是如何保證多線程環境下的可見性,JAVA內存模型JMM談談你對它的了解”

4. 官試官:“你能編寫一個volatile修飾的變量在多線程環境可見性示例不?”

5.?面試官:“為什么volatile不保證原子性呀,你知道底層原理么?”

6. 面試官:“你可以編寫一下,volatile不保證原子性的解決示例?”

7. 面試官:volatile能禁止指令重排 ,為什么有指令重排,volatile中怎樣做到禁止指令重排?

8. 面試官:你在哪些地方用到過volatile?手寫一個Volatile單例

?


1. 面試官:“請談談你對volatile的理解”

小李子竊竊私語,這不是正好前段時間復習且項目中使用到的volatile關鍵字么?于是小李子自信地答道:

volatile是Java虛擬機提供的輕量級的同步機制,volatile 是一個類型修飾符。volatile 的作用是作為指令關鍵字,確保本條指令不會因編譯器的優化而進行指令重排序,同時保證多線程環境下變量值變修改后,其他線程可見性;但volatile不保證原子性哦。使用示例:

volatile int number = 0; // 使用volatile 修飾整型變量number,以保證多線程環境下可見性及禁止指令重排。注:volatile不保證原子性
  • 1.1 保證多線程的可見性
  • 1.2 不保證原子性
  • 1.3 禁止指令重排,一般在單例模式下使用較多

2. 面試官接著問:“既然volatile不能保證原子性,那工作中如何解決這個問題呢?”

小李子心想,還來了個連環炮,好在我有準備。于是比利比利地回答:

工作中,我們有兩種方式規避這個問題:

1.?使用JDK提供的?Atomic原子類

比如:AtomicInteger來聲明變量,是采用了CAS 比較并交換 compareAndSwapInt,底層調用的是native方法,其意思是通過hotspot底層c/c++方法實現。最終實現是調用了?cmpxchg,cmpxchg指令在多線程下也是有可能被打斷,所以在加入lock指令?不允許其他線程訪問這塊內存區域的數據。

2. 加鎖,如synchronized 或?ReentrantLock


3. 官試官:“volatile是如何保證多線程環境下的可見性,JAVA內存模型JMM談談你對它的了解”

小李子心底陣陣發涼,前面已經回答的很好,還接著問,有完沒完!沒辦法,回憶一下,繼續答道:

Java內存模型(Java Memory Model,簡稱JMM) ?本身是一種抽象的概念并不真實存在,它描述的是一組規則或規范通過規范定制了程序中各個變量(包括實例字段、靜態字段和構成數組對象的元素)的訪問方式。

JMM關于同步規定:

  • 線程解鎖前,必須把共享變量的值刷新回主內存
  • 線程加鎖前,必須讀取主內存的最新值到自己的工作內存
  • 加鎖解鎖是同一把鎖
  • 由于JVM運行程序的實體是線程,而每個線程創建時JVM都會為其創建一個工作內存(有些地方成為棧空間),工作內存是每個線程的私有數據區域,而Java內存模型中規定所有變量都存儲在主內存,主內存是共享內存區域,所有線程都可訪問,但線程對變量的操作 (讀取賦值等) 必須在工作內存中進行,首先要將變量從主內存拷貝到自己的工作空間,然后對變量進行操作,操作完成再將變量寫回主內存,不能直接操作主內存中的變量,各個線程中的工作內存儲存著主內存中的變量副本拷貝,因此不同的線程無法訪問對方的工作內存,線程間的通訊(傳值) 必須通過主內存來完成。?

    這樣子吧,我畫一個JMM內存模型圖出來看看就清楚了。JMM內存模型圖如下:


    4. 官試官:“你能編寫一個volatile修飾的變量在多線程環境可見性示例不?”

    小李子聽到這個就想要罵娘了,還得編一個示例。不過,小Case,小李子接過鍵盤,啪啦啪啦地敲下代碼:

    package com.java.meet.c01_11_volatile;import java.time.LocalDateTime; import java.util.concurrent.TimeUnit;class MyResource {//int number = 0; // 此行代碼在多線程環境下,變量修改后不可見volatile int number = 0; // 此行代碼在多線程環境下,變量修改后可見,因為變量被 volatile修飾public void addT060(){this.number = 60;}}public class C_02_Volatile_SeeOK {public static void main(String[] args) { // main是一切方法的運行入口seeOkByVolatile();}// volatile 可以保證可見性,及時通知其它線程,主物理內存的值已經被修改。// volatile 是通過內存屏障實現private static void seeOkByVolatile() {MyResource res = new MyResource(); // 資源類new Thread(() -> {System.out.println(LocalDateTime.now() + "\t" + Thread.currentThread().getName() + "線程\t當前值為:" + res.number);// 暫停一會兒線程try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e){ e.printStackTrace();}res.addT060();System.out.println(LocalDateTime.now() + "\t" + Thread.currentThread().getName() + "線程\t當前值為:" + res.number);}, "AAAA").start();// 第2個線程就是我們的main線程while(res.number == 0){// main線程就一直在這里等待循環,走到number值不再等于零}System.out.println(LocalDateTime.now() + "\t" + Thread.currentThread().getName() + "線程\t當前值為" + res.number);}}

    沒有被volatile修飾變量,在多線程中被修改值,測試結果如下:?

    被volatile修飾變量,在多線程中被修改值,測試結果如下:?

    敲出來代碼了,哈哈,小李子心里哈哈的暗自高興~?


    5.?面試官:“為什么volatile不保證原子性呀,你知道底層原理么?”

    小李子,捋了下思路,這個So easy嘛。說道:number++在多線程下是非線程安全的。當我們添加volatile 關鍵字修飾時,n++ 同樣被拆分成了3個指令,在多線程環境下,依然不能保證原子性。如下圖,是volatile 修飾整型變量n,對n++方法進行反匯編。

    package com.java.meet.c01_11_volatile;/*** 6_volatile不保證原子理論解釋** 使用javap -c或javap -verbose*/public class C_06_T1 {volatile int n = 0;/*** MyData.java ====> MyData.class ===> 字節碼* n++ 被拆分成了3個指令* 執行getfield拿到原始n;* 執行iadd進行加1操作;* 執行putfield寫把累加后的值寫回** 查看字節碼,需要配置好External tools*//**/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/javap -c com.java.meet.c01_11_volatile.C_06_T1Compiled from "C_06_T1.java"public class com.java.meet.c01_11_volatile.C_06_T1 {volatile int n;public com.java.meet.c01_11_volatile.C_06_T1();Code:0: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: iconst_06: putfield #2 // Field n:I9: returnpublic void add();Code:0: aload_01: dup2: getfield #2 // Field n:I5: iconst_16: iadd7: putfield #2 // Field n:I10: return}Process finished with exit code 0*/public void add(){n++;} }

    6. 面試官:“你可以編寫一下,volatile不保證原子性的解決示例?”

    小李子胸有成竹的說:這樣吧,我演示一個volatile修飾的變量在多線程環境下不保證原子性的及其中一個解決volatile不保證原子性辦法。其中,可以通過JDK提供的Atomic原子類來保證原子操作,于是,拿起鍵盤噠噠地敲起來:

    package com.java.meet.c01_11_volatile;import java.util.concurrent.atomic.AtomicInteger;class MyNumber {volatile int number = 0;// 請注意,此時number前面是加了volatile關鍵字修飾的,volatile不保證原子性public void addPlusPlus(){number++;}// 使用JDK提供的原子類,可以解決volatile不保證原子性問題,采用CAS比較并交換AtomicInteger atomicInteger = new AtomicInteger();public void addMyAtomic(){atomicInteger.getAndIncrement();} }public class C_03_Volatile_NotSupportAtomic {public static void main(String[] args) { // main是一切方法的運行入口notSupportAtomicByVolatile();}// volatile 不保證原子性 及 使用JDK Atomic原子類解決volatile不保證原子性問題private static void notSupportAtomicByVolatile() {MyNumber res = new MyNumber();for (int i = 0; i < 20; i++) {new Thread(() -> {for (int j = 0; j < 1000; j++) {res.addPlusPlus();res.addMyAtomic();}}, String.valueOf(i)).start();}// 需要等待上面20個線程都全部計算完成后,再用main線程取得最終的結果值看是多少?while (Thread.activeCount() > 2){Thread.yield(); // yield我不執行,讓其他的線程更好地執行}System.out.println(Thread.currentThread().getName() + "\t int type,finally number value:" + res.number);System.out.println(Thread.currentThread().getName() + "\t AtomicInteger type,finally number value:" + res.atomicInteger);} }

    volatile不保證原子性測試結果如下:?


    7. 面試官:volatile能禁止指令重排 ,為什么有指令重排,volatile中怎樣做到禁止指令重排?

    小李子,心里苦呀,我只是想拿月薪30K的薪資,還得挖那么深,沒有辦法。繼續回答:

    計算機在執行程序時,為了提高性能,編譯器和處理器常常會做指令重排,一把分為以下3種

  • 編譯器優化的重排
  • 指令并行的重排
  • 內存系統的重排
  • 單線程環境里面確保程序是最終執行結果和代碼順序執行的結果一致。處理器在進行重新排序是必須要考慮指令之間的數據依賴性

    多線程環境中線程交替執行,由于編譯器優化重排的存在,兩個線程使用的變量能否保持一致性是無法確定的,結果無法預測。

    volatile實現禁止指令重排優化,從而避免多線程環境下程序出現亂序執行的現象。

    先了解一個概念,內存屏障(Memory Barrier)又稱內存柵欄,是一個CPU指令,它的作用有兩個:

  • 一是保證特定操作的執行順序,
  • 二是保證某些的內存可見性(利用該特性實現volatile的內存可見性)
  • 由于編譯器和處理器都能執行指令重排優化。如果在指令插入一條Memory B?和這條Memory Barrier指令重排序,也就是說通過插入內存屏障禁止在內存屏障前后的指令執行重排序優化。內存屏障另外一個作用是強制刷出各種CPU的緩存數據,因此任何CPU上的線程都能讀取到這些數據,因此任何CPU上的線程都能讀取到這些數據的最新版本。

    • 對volatile變量進行寫操作時,會在寫操作后加入一條store屏障指令,將工作內存中的共享變量值刷新回到主內存
    • 對volatile變量進行讀操作時,會在讀操作前加入一條load屏障指令,從主內存中讀取共享變量


    8. 面試官:你在哪些地方用到過volatile?手寫一個Volatile單例

    小李子喜出望外,這不是送分題。通過DCL雙端檢查 + Volatile,來實現,卡拉卡拉地寫下如下代碼:

    package com.java.meet.c01_11_volatile;import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.concurrent.TimeUnit;/*** 單例模式:volatile版本**/ public class C_10_SingletonDemo {/*** 多線程環境下,單例模式下,需要DCL機制 + volatile禁止指令重排*///private static C_10_SingletonDemo instance = null; // 在非常高的并發情況下,可能獲取的對象不是同一個private static volatile C_10_SingletonDemo instance = null; // 在非常高的并發情況下,DCL雙端檢查 + volatile 可以保證獲取的是同一個對象// 單例類構造方法私有化private C_10_SingletonDemo() {System.out.println(Thread.currentThread().getName() + "\t我是構造方法SingletonDemo()");}// 如果單純依靠 DCL (Double Check Lock雙端檢鎖機制),還是有問題,可能運行1000萬次,才出一次問題/*** DCL(雙端檢鎖) 機制不一定線程安全,原因是有指令重排的存在,加入volatile可以禁止指令重排** 原因在于某一個線程在執行到第一次檢測,讀取到的instance不為null時,instance的引用對象可能沒有完成初始化.** instance=new SingletonDem(); 可以分為以下步驟(偽代碼)** memory=allocate(); //1.分配對象內存空間** instance(memory); //2.初始化對象** instance=memory; //3.設置instance的指向剛分配的內存地址,此時instance!=null** 步驟2和步驟3不存在數據依賴關系.而且無論重排前還是重排后程序執行的結果在單線程中并沒有改變,因此這種重排優化是允許的.** memory=allocate(); //1.分配對象內存空間** instance=memory; //3.設置instance的指向剛分配的內存地址,此時instance!=null 但對象還沒有初始化完.*/public static C_10_SingletonDemo getInstance(){if (instance == null){synchronized (C_10_SingletonDemo.class){if (instance == null){instance = new C_10_SingletonDemo();}}}if (instance == null) {System.out.println("----");}return instance;}// List本身是不安全的, 使用以下才安全public static List<C_10_SingletonDemo> list = Collections.synchronizedList(new ArrayList<C_10_SingletonDemo>());public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 30; i++) {new Thread(() -> {list.add(C_10_SingletonDemo.getInstance());}, String.valueOf(i)).start();}// 等待上述操作完成TimeUnit.SECONDS.sleep(2);boolean oneSingleObject = true;for (int i = 0; i < list.size(); i++) {for (int j = i+1; j < list.size(); j++) {if (list.get(i) != list.get(j)) {System.out.println("此單例,創建了不同的對象實例!!!\t" + i + " "+ list.get(i) + "\t" + list.get(j));oneSingleObject = false;}}}if (oneSingleObject) {System.out.println("通過單例類獲取:" + list.size() + " 次依然是同一個對象!");}} }

    DCL雙端檢查 + Volatile 單例測試結果如下:?

    面試官,看來你對volatile掌握得還不錯哈~?

    今天面試,先到這里,回去等通過吧。


    文章最后,給大家推薦一些受歡迎的技術博客鏈接:

  • JAVA相關的深度技術博客鏈接
  • Flinak 相關技術博客鏈接
  • Spark?核心技術鏈接
  • 設計模式 —— 深度技術博客鏈接
  • 機器學習 —— 深度技術博客鏈接
  • Hadoop相關技術博客鏈接
  • 超全干貨--Flink思維導圖,花了3周左右編寫、校對
  • 深入JAVA 的JVM核心原理解決線上各種故障【附案例】
  • 請談談你對volatile的理解?--最近小李子與面試官的一場“硬核較量”
  • 聊聊RPC通信,經常被問到的一道面試題。源碼+筆記,包懂
  • 深入聊聊Java 垃圾回收機制【附原理圖及調優方法】

  • 歡迎掃描下方的二維碼或 搜索 公眾號“大數據高級架構師”,我們會有更多、且及時的資料推送給您,歡迎多多交流!

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    ?? ? ??

    ?

    總結

    以上是生活随笔為你收集整理的请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量”的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 男人干女人视频 | 日av一区 | 国产成人无码精品久久久久 | 免费在线色 | 成人性生生活性生交3 | 久久精品大全 | 综合久久久久久 | 97激情| 30一40一50老女人毛片 | 国产精品36p | 最新色网址 | 日韩成人精品在线观看 | 男人天堂网址 | 中文字幕无码日韩专区免费 | 91视频最新入口 | 校霸被c到爽夹震蛋上课高潮 | 黄色最新网址 | 亚洲欧美日韩另类 | 久操欧美 | 欧美一区二区三区视频在线观看 | 精品成人一区二区三区 | 38激情| 91激情 | 内射毛片内射国产夫妻 | 黄色一级片黄色一级片 | 日本韩国免费观看 | 国产精品美女www | 成人h动漫精品一区二区无码 | 少妇视频在线播放 | 伊人久操视频 | 中国一级特黄毛片大片 | 韩国日本在线观看 | av天天射 | 国产午夜电影在线观看 | 亚洲久久在线观看 | 精品视频在线一区二区 | 午夜va| 久久久噜噜噜www成人网 | 91久久色| 欧美激情五月 | 污视频在线观看网址 | 国产剧情av在线播放 | 亚洲精品电影在线观看 | 青青草视频网站 | 日韩人成 | 麻豆视频传媒入口 | 日本激情一区 | 自拍偷拍综合 | 伊人av在线播放 | 亚洲一区二区不卡在线观看 | 国产a自拍 | 男女拍拍拍网站 | 神马香蕉久久 | 天堂俺去俺来也www 欧美大片在线播放 | 蜜臀麻豆 | 伊人96| 久久国产区 | 亚洲自偷自偷偷色无码中文 | 免费成人av | 91在线最新| 韩国一级淫片免费看 | 亚洲图片欧美激情 | 黄色一级在线视频 | 国产只有精品 | 男生和女生一起搞鸡 | 中文字幕无码精品亚洲资源网久久 | 雪白的扔子视频大全在线观看 | 91精品国产自产精品男人的天堂 | 亚州国产 | 亚洲欧美一区二区三区在线观看 | 一区二区三区视频播放 | 免费黄色在线视频 | 91亚洲国产成人久久精品网站 | 中文字幕在线观看免费 | 女同激情久久av久久 | 夜夜嗨老熟女av一区二区三区 | 成人a毛片久久免费播放 | 欧美一级在线观看 | 国产一区二区视频在线观看 | 中国女人特级毛片 | 国产丝袜精品视频 | 探花精品 | 免费色站 | 天天拍天天操 | 69av网站 | 亚洲欧美日本在线 | 欧美爱爱网 | 99久久人妻无码精品系列 | 亚洲精品在线网站 | 麻豆av一区二区 | 国产男女猛烈无遮挡免费视频 | 亚洲综合一区中 | 污污视频在线播放 | 国产精品资源在线 | 美女网站免费视频 | 国产精品久久久久影院老司 | 亚洲91av| 欧美日韩看片 | www.黄色片网站 |