知道這些,面試時volatile就穩了

在Java相關的崗位面試中,很多面試官都喜歡考察面試者對Java併發的瞭解程度,而以volatile關鍵字作爲一個小的切入點,往往可以一問到底,把Java內存模型(JMM),Java併發編程的一些特性都牽扯出來,深入地話還可以考察JVM底層實現以及操作系統的相關知識。

  • 本文以一次假想的面試過程,來深入瞭解下volitile關鍵字【本菜雞還沒投簡歷,準備好被今年20年秋招的毒打了😭】
  • 題目有標題黨的嫌疑,但是如果大家好好理解文中涉及到的兩篇文章,相信你對volatile有更深刻的認識!

【靈魂拷問開始】

  1. 面試官:Java併發這塊瞭解的怎麼樣?說說你對volatile關鍵字的理解?
  2. 面試官:能不能詳細說下什麼是內存可見性,什麼又是重排序呢?
  3. 面試官:volatile怎麼保證可見性的?多個線程之間的可見性,你能講一下底層原理是怎麼實現的嗎?
  4. 面試官:volatile關鍵字是怎麼保證有序性的?
  5. 面試官:volatile能保證可見性和有序性,但是能保證原子性嗎?爲什麼?
  6. 面試官:瞭解過JMM內存模型嗎?簡單的講講

到這裏,我的眼裏已是常含淚水了。不是因爲我對代碼愛的深沉,而是因爲我菜的真誠!

沒事,不就是個破volatile嗎?別唸了,我學習還不行嗎!

Q1:請你談談對volatile關鍵字的理解?

volatile是JVM提供的輕量級的同步機制

  1. 保證可見性

  2. 保證有序性,禁止指令重排

  3. 不保證原子性(需要藉助synchronized或者CAS)

小夥子,不錯麼😊,回答對了 1 + 1,得來點 2 + 2 的難度了


Q2:什麼是內存可見性,volatile怎麼保證多個線程之間的可見性的?

問題2和問題3講到的可見性,用JMM來解釋的話,本質上是同一個問題。至於有序性和重排序,到問題4再討論。

一問到內存的可見性,volatile相關的,直接就把JMM內存模型搬出來好吧。先放圖,然後再表演。

以下是俺個人的回答,有不足或漏洞,歡迎大家更正指出!

所謂可見性,是指當一條線程修改了共享變量的值,新值對於其他線程來說是可以立即得知的

每個線程都有自己獨立的工作區間,爲了匹配CPU的運行速度,他們不會直接從內存中讀取數據,而是將數據拷貝一份到CPU緩存中(即每個線程自己的工作內存),他們之間的相互交互,是通過內存來完成的。

根據JMM內存模型的8大原子操作,每個線程在j將數據操作完stroe回主存之前,會加lock指令來鎖定內存區域的緩存(緩存行鎖定),根據MESI緩存一致性協議,總線通過偵聽器發現數據被修改,會立即讓其他線程工作內存中不一致的副本立即失效。

等到當前線程將更改後的數據write回主存後,立即執行unlock指令。

此時,其他線程再重新讀取更新後的數據,再拷貝到自己的工作內存。總線偵聽機制會在總線上檢測線程的數據,發現有線程做了更改時準備store回主內存時,它就會立刻將其他線程工作內存中的副本置位無效,然後從新到主存獲取更新後的值。

除了使用 volatile 關鍵字來保證內存可見性之外,使用synchronizedLock鎖也能保證變量的內存可見性。只是相比而言使用 volatile關鍵字開銷更小,是輕量級的鎖。

這就是內存可見性的原理。


Q3:volatile關鍵字是怎麼保證有序性的?

使用volatile關鍵字修飾共享變量便可以禁止指令重排序。若用volatile修飾共享變量,在JVM底層volatile是採用“內存屏障”來實現禁止特定類型的處理器重排序。加入volatile關鍵字時,會多出一個lock前綴指令,lock前綴指令實際上相當於一個內存屏障(也成內存柵欄),內存屏障會提供3個功能:

  1. 它確保指令重排序時不會把其後面的指令排到內存屏障之前的位置,也不會把前面的指令排到內存屏障的後面;即在執行到內存屏障這句指令時,在它前面的操作已經全部完成;

  2. 它會強制將對緩存的修改操作立即寫入主存;

  3. 如果是寫操作,它會導致其他CPU中對應的緩存行無效。

JMM具備一些先天的有序性,通過Happens-Before原則就可以保證的一定的有序性。


Q4:volatile能保證可見性和有序性,但是能保證原子性嗎?爲什麼?

volatile關鍵字不能保證原子性。

a. 當寫一個volatile變量時,JMM會把該線程本地內存中的變量強制刷新到主內存中去;

b. 這個寫會操作會導致其他線程中的緩存無效。

對於類似i++這樣的複合操作,要想保證原子性,只能藉助於synchronizedLock以及併發包下的AtomicInteger的原子操作類。AtomicInteger對基本數據類型的 自增(加1操作),自減(減1操作)、以及加法操作(加一個數),減法操作(減一個數)進行了封裝,保證這些操作是原子性操作。


Q5:瞭解過JMM內存模型嗎?簡單的講講

看完這篇👇文章,這道題目就是你的主場。

👉用volatile的視角,來打開JMM內存模型👈

看着這張圖,直接就巴拉巴拉一頓操作!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章