瞭解Java內存模型,看完這一篇就夠了

前言(此文草稿是年前寫的,但因爲瑣事甚多一直未完善好。清明假無事,便收收尾發佈了)java

    年關將近,我的工做學習怠惰了很多。兩年前剛作開發的時候,信心滿滿想看看一我的經過本身的努力,最終能達到一個什麼樣的高度。而近半年面試

深陷生活的泥淖中,卻有點被壓迫住的感受。我的成長、家庭、父母、朋友、身邊的人,無不或多或少的影響着個人心境。不少時候仍是要多反思一些,編程

經過思考讓本身重拾信心,繼續打滿雞血的前行。中國當前的大環境縱然有波折,但整體是向上的,互聯網行業也是出於深度改造各行各業的狀態,並且數組

我的對計算機對編程頗有熱情,一息理想尚存,想要本身的人生有所不一樣。因此無論怎樣,這條路還要好好的走下去。這個把月多學習吧,爲節後的緩存

機會最好準備。併發

正文app

    閒話少敘,下面開始正題。首先要明確內存模型指什麼。書中的定義是:在特定的操做協議下,對特定內存和高速緩存進行讀寫訪問的過程抽象學習

能夠知道,內存模型就是來規定如何對內存/緩存進行讀寫操做的。因此Java內存模型,就是用來定義程序對java內存的的訪問規則。進一步說, java內存spa

模型就是定義程序中變量(靜態變量、數組對象元素等,不包括局部變量、方法參數)的訪問規則。線程

Java內存模型的規定:

一、全部變量存儲在主內存中;

二、每一個線程都有本身的工做內存,且對變量的操做都是在工做內存中進行;

三、不一樣線程之間沒法直接訪問彼此工做內存中的變量,要想訪問只能經過主內存來傳遞。

java的線程、工做內存、主內存關係以下圖所示:

 

具體變量從主內存到工做內存,以及從工做內存轉回主內存的實現細節,由下面八個原子性的操做完成:

lock:做用於主內存變量,將該變量標識爲一個線程獨佔的狀態

unlock:做用於主內存變量,將獨佔狀態釋放

read:做用於主內存變量,將值拷貝到工做內存中

load:做用於工做內存中的變量,將值放到工做內存中的變量副本中

use:做用於工做內存中的變量,將值傳給執行引擎

asign:做用於工做內存中的變量,將執行引擎中的值賦給工做內存中的變量

store:做用於工做內存中的變量,將值傳給主內存

write:做用於主內存中的變量,將工做內存中返回的值放到主內存變量中

同時還對上述八個操做進行了一些細節的要求,好比read/load、store/write必須成對出現,未執行過lock的變量不能執行unlock操做等。

 

劃重點,此處面試常遇到的問題就是對於volatile關鍵字的解讀。

volatile關鍵字

此關鍵字修飾的變量具備兩種效果:一、保證線程間的可見性;二、阻止指令重排序

對於1的實現,它保證load與use必須相鄰調用,即要use這個變量,一定先執行read/load,這樣每次都能獲取到最新的變量值;它又保證asign與store

必須相鄰調用,即在工做內存中將該變量改了以後,一定會先同步到主內存中。這樣,volatile關鍵字實現了可見性。至於阻止指令重排序,仍是移步

《深刻理解java虛擬機》一書吧,貧道水平有限,就不在這裏說了。

 

從另外一個角度來分析,Java內存模型是圍繞着在併發過程當中如何處理原子性、可見性、有序性來創建的。

原子性:八個原子性操做,以及synchronized(lock/unlock未直接開放給用戶,synchronized經過monitorenter跟monitorexit指令調用的lock/unlock操做)

可見性:volatile、synchronized、final這三個關鍵字均經過不一樣方式實現了可見性

有序性:volatile、synchronized  這兩個關鍵字保證有序性,同時還有先行發生(happens-before)原則來保證隱含的默認有序性

下面說說happens-before先行發生原則,先行發生原則用通俗語言表述就是:若是操做A在操做B以前發生,那麼A產生的影響B一樣能觀測到。那麼問題來

了,先行發生原則都有哪些呢?一樣有八條,以下:

程序次序規則:同一個線程中按照代碼的順序依次執行

管程鎖定規則:對於同一個鎖,unlock先行發生於後面的lock,即unlock了纔會lock

volatile變量規則:對一個volatile變量的寫操做先行發生於後面對該變量的讀操做,即寫完了纔會讀

線程啓動規則:一個線程的start()方法先行發生於此線程的任何一個動做

線程終止規則:一個線程的全部動做先行發生於該線程的終止檢測

線程中斷規則:對一個線程interrupt()方法的調用先行發生於線程的中斷檢測Thread.interrpted()

對象終結規則:對象的初始化完成先行發生於finalize()方法

傳遞性:顧名思義,A先行發生於B,B先行發生於C,則A必定先行發生於C

 

總結

    java內存模型基本就這些內容,若是都掌握了的話,非一線互聯網公司基本都能應對自如了(由於一線互聯網公司貧道本人也沒進去><)。

相關文章
相關標籤/搜索