久久综合九色综合97婷婷-美女视频黄频a免费-精品日本一区二区三区在线观看-日韩中文无码有码免费视频-亚洲中文字幕无码专区-扒开双腿疯狂进出爽爽爽动态照片-国产乱理伦片在线观看夜-高清极品美女毛茸茸-欧美寡妇性猛交XXX-国产亚洲精品99在线播放-日韩美女毛片又爽又大毛片,99久久久无码国产精品9,国产成a人片在线观看视频下载,欧美疯狂xxxx吞精视频

有趣生活

當前位置:首頁>職場>面試常問的adb(有了解過volatile關鍵字嗎)

面試常問的adb(有了解過volatile關鍵字嗎)

發布時間:2024-01-24閱讀(13)

導讀目前正在出一個Java多線程專題長期系列教程,從入門到進階含源碼解讀,篇幅會較多,喜歡的話,給個關注??~本篇內容純理論一點,下面我們就來說一說關于面試常問....

目前正在出一個Java多線程專題長期系列教程,從入門到進階含源碼解讀, 篇幅會較多, 喜歡的話,給個關注?? ~ 本篇內容純理論一點,下面我們就來說一說關于面試常問的adb?我們一起去了解并探討一下這個問題吧!

面試常問的adb(有了解過volatile關鍵字嗎)

面試常問的adb

面試官: 有了解過volatile關鍵字嗎 說說看前言

目前正在出一個Java多線程專題長期系列教程,從入門到進階含源碼解讀, 篇幅會較多, 喜歡的話,給個關注?? ~ 本篇內容純理論一點

概念回顧

首先我們回顧一下之前講的基本概念:

內存可見性

「內存可見性,指的是線程之間的可見性,當一個線程修改了共享變量時,另一個線程可以讀取到這個修改后的值」

重排序

為優化程序性能,對原有的指令執行順序進行優化重新排序。重排序可能發生在多個階段,比如編譯重排序、CPU重排序等。

happens-before

遵循happens-before規則,JVM就能保證指令在多線程之間的順序性符合執行的預期。

volatile
  • 保證變量的「內存可見性」
  • 禁止volatile變量與普通變量「重排序」

那么這個內存可見性過程是怎么樣的呢?之前也有給大家演示過具體代碼,這里直接給大家總結一下:

所謂內存可見性, 當一個線程對volatile修飾的變量進行操作時,會立即將本地內存中的共享變量刷新到主內存, 同理,當進行操作時,會立即將本地內存失效,從主內存中讀取共享變量的值。

在這一點上,volatile與鎖具有相同的內存效果,volatile變量的寫和鎖的釋放具有相同的內存語義,volatile變量的讀和鎖的獲取具有相同的內存語義。

禁止重排又是怎么回事呢?

在JSR-133之前的舊的Java內存模型中,是允許volatile變量與普通變量重排序的。想想看,如果可重排,會發生什么?

我們假設有兩個線程A和B,一個被volatile修飾的變量a,一個未被修飾的普通變量b,看下邊代碼:

volatile a = 1;int b = 2;public void writer() { a = 1; b = 3;}public void reader() { if (a == 1) { System.out.println(b); }}

線程A執行writer方法,首先將a設置為1,此時B線程操作reader方法,此時判斷a=1,然后進行輸出b=2,線程A多b操作設置為3,其實最終結果應該b=3才對,所以這里重排可能會導致普通變量讀錯的情況

為了提供一種比鎖更輕量級的「線程間的通信機制」JSR-133決定增強volatile的內存語義:嚴格限制編譯器和處理器對volatile變量與普通變量的重排序。那么它是怎么禁止的呢?答案是通過內存屏障,或許你聽說過這個概念,下面我們一起看一下~

內存屏障

什么是內存屏障呢?在計算機中,主要分為兩種,一種是讀屏障(Load Barrier)寫屏障(Store Barrier)。內存屏障有兩個作用:

  • 阻止屏障兩側的指令重排序
  • 強制把寫緩沖區/高速緩存中的臟數據等寫回主內存,或者讓緩存中相應的數據失效。(這里的緩存指的是cpu的多級緩存如L1,L2)

我們寫的代碼最終都是要通過編譯器的,那么編譯器是怎么實現這個過程的呢?

編譯器在生成字節碼的時候,會在指令序列中插入內存屏障來禁止特定類型的處理器重排序。在Java中,JMM內存屏障插入策略可以保證各平臺處理器下程序的volatile內存語義正確,具體策略:

  • 在每個volatile寫操作前插入一個屏障;
  • 在每個volatile寫操作后插入一個屏障;
  • 在每個volatile讀操作后插入一個屏障;
  • 在每個volatile讀操作后再插入一個屏障。

volatile與普通變量的重排序規則:

  1. 如果第一個操作是volatile讀,那無論第二個操作是什么,都不能重排序;
  2. 如果第二個操作是volatile寫,那無論第一個操作是什么,都不能重排序;
  3. 如果第一個操作是volatile寫,第二個操作是volatile讀,那不能重排序。

那么如果第一個操作是普通變量讀,第二個是volatile讀,可以重排嗎?

答案: 可以的

volatile使用場景

相信在了解以上概念之后,對它應該有一定的認識了, volatile可以保證內存可見性且禁止重排序, 它跟又具有相同的內存語義,又被稱為輕量級鎖。volatile僅僅保證對單個volatile變量的讀/寫具有原子性,而鎖可以保證整個「臨界區代碼」的執行具有原子性。所以更高級一點。但也不是說volatile就不好,作為輕量級的鎖,某些場景下還是非常有用的。

我們以雙重鎖檢查單例模式為例,首先我們看一下普通的單例模式:

class Singleton { private static Singleton instance; private Singleton() {} public Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; }}

單線程下你可以這么搞,沒毛病,多線程下就不行了,所有我們要加,于是雙重鎖檢查下的實現:

class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if(instance == null) { synchronized (Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; }}

這樣就真沒問題了嗎疑問?我們知道在new的時候,主要做了三件事:

  • 分配內存
  • 變量賦值
  • 初始化對象

這個過程中,可能會導致指令重排,有可能你會說里邊加了,上節給大家介紹順序一致性模型中,我們講過,在同步模式下臨界區內的代碼可以發生重排序,所以這里還是有可能發生重排序的,所以最終的這個過程,可能會這樣:

線程A執行 分配內存 -> 變量賦值, 線程B執行 判斷 instance不為null 開始訪問對象,實際上對象還未初始化,所以這時候,我們就要加上volatile

class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if(instance == null) { synchronized (Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; }}

這樣在多線程環境下,可以保證其安全性

結束語

本節內容可能不像之前那么好理解,比較抽象,所以本文也有不足的地方,大家自己可以多查查一些資料,綜合理解, 不要去背概念。本節我們提到了鎖的概念,下一節,帶大家深入學習一下Java的synchronized與鎖 ~

往期內容推薦
  • Java多線程專題之線程與進程概述
  • Java多線程專題之線程類和接口入門
  • Java多線程專題之進階學習Thread(含源碼分析)
  • Java多線程專題之Callable、Future與FutureTask(含源碼分析)
  • 面試官: 有了解過線程組和線程優先級嗎
  • 面試官: 說一下線程的生命周期過程
  • 面試官: 說一下線程間的通信
  • 面試官: 說一下Java的共享內存模型
  • 面試官: 有了解過指令重排嗎,什么是happens-before
  • 我的博客(閱讀體驗較佳)
  • 寫給初學者的Java基礎教程
  • 一文帶你快速學習Java集合類
  • 花幾分鐘快速了解一下泛型與枚舉
  • Java注解與反射入門到進階
  • JavaIO教程從入門到進階
項目源碼(源碼已更新 歡迎star??)
  • java-thread-all
  • 地址: https://github.com/qiuChengleiy/java-thread-all.git
推薦 SpringBoot & SpringCloud (源碼已更新 歡迎star??)
  • springboot-all
  • 地址: https://github.com/qiuChengleiy/springboot-all.git
  • SpringBoot系列教程合集
  • 一起來學SpringCloud合集
,

歡迎分享轉載→http://www.avcorse.com/read-220039.html

Copyright ? 2024 有趣生活 All Rights Reserve吉ICP備19000289號-5 TXT地圖HTML地圖XML地圖