Volatile關鍵字從理解到實操,源碼實例深度剖析

談到并發編程 ,必知曉并發三要素 :原子性、可見性、有序性。而 Volatile 涉及了可見性與有序性,是輕量級的 synchronized ,在并發編程中扮演著極其重要的角色。

本文將從理論知識到源碼實例,深入剖析 Volatile 的實現原理,幫助快速掌握并正確使用 Volatile 變量:

1.Volatile關鍵字

2.Java內存模型

3.Volatile內存模型可見性

4.Volatile的工作原理

5.Volatile的源碼案例

在談 Volatile 之前,我們先回顧下 Java 內存模型的三要素:原子性、可見性、有序性,也就是大家常提到的并發編程三要素。

并發編程的三要素

1.原子性

和數據庫事務中的原子性一樣,滿足原子性特性的操作是不可中斷的,要么全部執行成功要么全部執行失敗

只有簡單的讀取、賦值(而且必須是將數字賦值給某個變量,變量之間的相互賦值不是原子操作)才是原子操作。

比如:i = 2;j = i;i++;i = i + 1;

上面4個操作中,i=2是讀取操作,必定是原子性操作,j=i你以為是原子性操作,其實吧,分為兩步,一是讀取i的值,然后再賦值給j,這就是2步操作了,稱不上原子操作,i++和i = i + 1其實是等效的,讀取i的值,加1,再寫回主存,那就是3步操作了。

所以上面的舉例中,最后的值可能出現多種情況,就是因為滿足不了原子性。

非原子操作都會存在線程安全問題,需要我們使用同步技術(sychronized)來讓它變成一個原子操作,java的concurrent包下提供了一些原子類:比如:AtomicInteger、AtomicLong等。

2.可見性

多個線程訪問同一個共享變量時,其中一個線程對這個共享變量值的修改,其他線程能夠立刻獲得修改以后的值

3.有序性

編譯器和處理器為了優化程序性能而對指令序列進行重排序,也就是你編寫的代碼順序和最終執行的指令順序是不一致的。

但是重排序過程不會影響到單線程程序的執行,卻會影響到多線程并發執行的正確性。

Volatile

Volatile 是一個Java語言的類型修飾符,一旦一個共享變量(類的成員變量、類的靜態成員變量)被Volatile修飾之后,那么就具備了兩層語義:

1、保證多線程下的可見性

2、禁止進行指令重排序(即保證有序性)

這里需要注意一個問題,Volatile只能讓被他修飾內容具有可見性、有序性。Volatile只能保證對單次讀/寫的原子性,i++ 這種操作不能保證原子性。

Volatile的內存模型

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

試圖屏蔽各種硬件和操作系統的內存訪問差異,以實現讓 Java 程序在各種平臺下都能達到一致的內存訪問效果。

Java內存模型規定了所有的變量都存儲在主內存中,每條線程還有自己的工作內存,線程的工作內存中保存了該線程中是用到的變量的主內存副本拷貝,線程對變量的所有操作都必須在工作內存中進行,而不能直接讀寫主內存。不同的線程之間也無法直接訪問對方工作內存中的變量,線程間變量的傳遞均需要自己的工作內存和主存之間進行數據同步進行。

1)主內存主要存儲的是Java實例對象,所有線程創建的實例對象都存放在主內存中,不管該實例對象是成員變量還是方法中的本地變量(也稱局部變量),當然也包括了共享的類信息、常量、靜態變量。由于是共享數據區域,多條線程對同一個變量進行訪問可能會發現線程安全問題。

2)工作內存每條線程都有自己的工作內存(Working Memory,又稱本地內存,可與前面介紹的處理器高速緩存類比),線程的工作內存中保存了該線程使用到的變量的主內存中的共享變量的副本拷貝。工作內存是 JMM 的一個抽象概念,并不真實存在。它涵蓋了緩存,寫緩沖區,寄存器以及其他的硬件和編譯器優化。

主要存儲當前方法的所有本地變量信息(工作內存中存儲著主內存中的變量副本拷貝),每個線程只能訪問自己的工作內存,即線程中的本地變量對其它線程是不可見的,就算是兩個線程執行的是同一段代碼,它們也會各自在自己的工作內存中創建屬于當前線程的本地變量,當然也包括了字節碼行號指示器、相關Native方法的信息。

Volatile的實現原理

Volatile 保證內存可見性

主內存和工作內存之間的交互有具體的交互協議,JMM定義了八種操作來完成,這八種操作是原子的、不可再分的,它們分別是:lock,unlock,read,load,use,assign,store,write。

其中,lock , unlock , read , write 作用于主內存; load ,use , assign , store 作用于工作內存

1) lock

將主內存中的變量鎖定,為一個線程所獨占

2) unclock

將lock加的鎖定解除,此時其它的線程可以有機會訪問此變量

3) read

將主內存中的變量值讀到工作內存當中

4) load

將read讀取的值保存到工作內存中的變量副本中。

5) use

將值傳遞給線程的代碼執行引擎。

6) assign

將執行引擎處理返回的值重新賦值給變量副本。

7) store

將變量副本的值存儲到主內存中。

8) write

將 store 存儲的值寫入到主內存的共享變量當中。

從主存復制變量到當前工作內存(read and load)

執行代碼,改變共享變量值 (use and assign)

用工作內存數據刷新主存相關內容 (store and write)

指令規則

1)read 和 load、store 和 write 必須成對出現。

2)assign 操作,工作內存變量改變后必須刷回主內存。

3)同一時間只能運行一個線程對變量進行 lock,當前線程 lock 可重入,unlock 次數必須等于 lock 的次數,該變量才能解鎖。

4)對一個變量 lock 后,會清空該線程工作內存變量的值,重新執行 load 或者 assign 操作初始化工作內存中變量的值。

5)unlock 前,必須將變量同步到主內存( store/write 操作)。

Volatile源碼案例

以上,是 Java 并發編程有關 Volatile 的實現原理。

關注『 mikechen的互聯網架構 』,回復“架構”,可獲取本篇文章的視頻詳解。

---END--

哈嘍,我是Mike,很高興認識你。

每篇深度技術文,都是我耗時2-5天用心創作的,如果大家看了覺得還行,謝謝【點贊+收藏+轉發】一鍵三連支持下。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,224評論 6 529
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,916評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,014評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,466評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,245評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,795評論 1 320
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,869評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,010評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,524評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,487評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,634評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,173評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,884評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,282評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,541評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,236評論 3 388
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,623評論 2 370

推薦閱讀更多精彩內容