Java面試官最喜歡問的關(guān)鍵字之volatile詳解

前言

創(chuàng)新互聯(lián)從2013年創(chuàng)立,我們提供高端網(wǎng)站建設(shè)、重慶小程序開發(fā)公司、電商視覺設(shè)計(jì)、重慶APP開發(fā)公司及網(wǎng)絡(luò)營銷搜索優(yōu)化服務(wù),在傳統(tǒng)互聯(lián)網(wǎng)與移動(dòng)互聯(lián)網(wǎng)發(fā)展的背景下,我們堅(jiān)守著用標(biāo)準(zhǔn)的設(shè)計(jì)方案與技術(shù)開發(fā)實(shí)力作基礎(chǔ),以企業(yè)及品牌的互聯(lián)網(wǎng)商業(yè)目標(biāo)為核心,為客戶打造具商業(yè)價(jià)值與用戶體驗(yàn)的互聯(lián)網(wǎng)+產(chǎn)品。

筆者去年面試過幾家公司,基本上每家公司都會問到volatile,甚至有的公司每輪面試的時(shí)候都會問到。面試官這么喜歡問volatile就是因?yàn)檫@個(gè)關(guān)鍵字涉及到的知識點(diǎn)較多比如Java內(nèi)存模型、內(nèi)存屏障、happen-befor等知識,可以繼續(xù)挖掘到系統(tǒng)指令、超線程等知識。

Java內(nèi)存模型(JMM)

volatile是Java虛擬機(jī)提供的最輕量的同步機(jī)制,但很難被正確的理解與使用,通過學(xué)習(xí)Java內(nèi)存模型對volatile專門定義的一些特殊訪問規(guī)則,或許會對理解volatile有一定幫助。

Java內(nèi)存模型定義了線程和內(nèi)存之間關(guān)系:線程之間的共享變量存儲在主內(nèi)存中,每個(gè)線程都有一個(gè)私有的本地內(nèi)存,本地內(nèi)存中存儲了該線程以讀 / 寫共享變量的副本。本地內(nèi)存是 JMM 的一個(gè)抽象概念,并不真實(shí)存在;它涵蓋內(nèi)存、緩存、寄存器以及其他的硬件和編譯器優(yōu)化。Java的內(nèi)存模型抽象如下:

Java面試官最喜歡問的關(guān)鍵字之volatile詳解

volatile的語義

volatile主要提供了兩種語義:

1,可見性:

可見性是指一個(gè)線程寫入的值,其他線程能夠立即讀取。在由Java內(nèi)存模型可知道,每個(gè)線程都是有本地內(nèi)存。所以線程A寫入在正常情況下,線程B不能立即讀取。但是在volatile變量,可以保證線程A不寫入本地內(nèi)存直接寫入主內(nèi)存,線程B直接從主內(nèi)存中讀取,不從本地內(nèi)存中讀取。

2,禁止指令重排序:

重排序是指編譯器和處理器為了優(yōu)化程序性能而對指令進(jìn)行重排序的一種優(yōu)化手段。

Java面試官最喜歡問的關(guān)鍵字之volatile詳解

Java程序的幾種重排序

  • 編譯器優(yōu)化重排序:編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執(zhí)行順序。
  • 指令級并行的重排序:如果不存在數(shù)據(jù)依賴性,處理器可以改變語句對應(yīng)機(jī)器指令的執(zhí)行順序。
  • 內(nèi)存系統(tǒng)的重排序:處理器使用緩存和讀寫緩沖區(qū),這使得加載和存儲操作看上去可能是在亂序執(zhí)行

volatile的技術(shù)基石--內(nèi)存屏障

內(nèi)存屏障是cpu指令,該指令保證特定操作的順序性和某些內(nèi)存的可見性。插入一條內(nèi)存屏障指令之后會告訴編譯器和CPU:不管什么指令都不能和這條指令重排序。內(nèi)存屏障所做的另外一件事情就是強(qiáng)制刷出各種CPU cache,如一個(gè)Write-Barrier(寫入屏障)將刷出所有在Barrier之前寫入cache的數(shù)據(jù),因此,任何CPU上的線程都能讀取到這些數(shù)據(jù)的最新版本。

對于Java程序而言,如果把加入volatile關(guān)鍵字的代碼和未加入volatile關(guān)鍵字的代碼都生成匯編代碼,會發(fā)現(xiàn)加入volatile關(guān)鍵字的代碼會多出一個(gè)lock前綴指令。

volatile的典型用例

狀態(tài)標(biāo)志,代碼示例如下:

Java面試官最喜歡問的關(guān)鍵字之volatile詳解

線程1執(zhí)行run()的過程中,可能有另外的線程2調(diào)用了shutdown,所以stop變量必須是volatile(利用的volatile的可見性)。

還有一種常見的用法在雙重檢驗(yàn)的單例實(shí)現(xiàn)上,代碼如下:

Java面試官最喜歡問的關(guān)鍵字之volatile詳解

instance = new Singleton()這句,這并非是一個(gè)原子操作,事實(shí)上在 JVM 中這句話大概做了下面 3 件事情:

  • 給 instance 分配內(nèi)存
  • 調(diào)用 Singleton 的構(gòu)造函數(shù)來初始化成員變量
  • 將instance對象指向分配的內(nèi)存空間(執(zhí)行完這步 instance 就為非 null 了)

如果instance變量沒有加volatile,因?yàn)橹噶钪嘏判虻拇嬖冢涂赡軐?dǎo)致執(zhí)行步驟是1-2-3,也可能是1-3-2。一旦是1-3-2,就可能會導(dǎo)致訪問未初始化的內(nèi)存。但是加上volatile關(guān)鍵字之后,一定保證是按照1-2-3步驟執(zhí)行的(利用的volatile的禁止重排序)。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對創(chuàng)新互聯(lián)的支持。

文章標(biāo)題:Java面試官最喜歡問的關(guān)鍵字之volatile詳解
網(wǎng)頁網(wǎng)址:http://bm7419.com/article30/jceepo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司、外貿(mào)網(wǎng)站建設(shè)搜索引擎優(yōu)化、響應(yīng)式網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)