本文部份內容選自<<深刻理解Java虛擬機>> 以及 CrazyDailyQuestion的ArtarisCNgit
Java 內存模型 , 即 Java Memory Model,JMM 來屏蔽各類硬件和操做系統的內存訪問差別,以實現讓Java 在各類平臺都達到一致的訪問效果.Java 內存模型規範了 JVM 如何 禁用緩存 和 編譯優化 的方法.github
下面我就用圖文並茂的方式給你們展現一下: Thread,Main Memory和Working Memory的交互關係緩存
那麼,變量是如何經過Main Memory copy給 Working Memory,如何從 Work Memory sync 到 Main Memory的呢?安全
jvm實現必須保證每一種操做都是原子的,不可細分的(double 和 long比較特殊)併發
Java 提出了 8種操做類型app
變量做用域: Main Memoryjvm
方法 | 做用 |
---|---|
lock(🔒) | 把Thread 設置線程獨有 Tag |
unlock(🔓) | 釋放變量,給其餘Thread使用 |
read(讀取) | 變量從Main Memory傳輸到Thread 的 Working Memory途徑 |
變量做用域: Working Memory優化
方法 | 做用 |
---|---|
load(載入) | 變量值放到Working Memory 的變量副本中 |
use(使用) | Working Memory的變量值傳給執行引擎,JVM收到須要執行的變量的字節碼指令時候,會執行這個操做 |
assign(賦值) | 他把一個從執行引擎接收的值賦給Working Memory 的變量,JVM收到須要執行的變量的字節碼指令時候,會執行這個操做 |
store(存儲) | 把變量值傳給 Main Memory |
變量做用域: Main Memorythis
方法 | 做用 |
---|---|
write(寫入) | Working Memory的變量放到Main Memory中 |
操做規則:操作系統
太官方,主要是爲了解決Java併發安全,Android用的不太多,只想理清流程,不想看細節~
沒有被volatile位數據能夠分割爲兩個32位進行操做,volatile和syhnronized功能相似,解決多Thread競爭問題
操做規則:
long 和 double 具備非原子性,不須要用考慮使用volatile修飾
原子性: 除了 long 和 double之外的基本數據類型都具備原子性
可見性: 當一個線程修改了這個值,其餘線程可以當即感知,即 Main Memory 傳遞的方式具備可見性
volatile 能保證新值能當即同步到 Main Memory,以及每次使用 從 Main Memory 當即 refresh.
final 字段在constrctor方法 init 後,constrctor 沒有把 "this" 引用傳遞出去(this 逃逸很是危險),那麼在其餘線程中就能看見 final 字段的值
synchronized 變量在同步代碼塊,unlock以後,必須回到 Main Memory,執行完write操做
有序性:
本線程中全部操做都是有序的(Whithin-thread As-if-Serial Semantics)
ThreadA watch ThreadB 都是無序的(指令重排,Main Memory與Working Memory 同步 延遲)
volatile 禁止指令重排
synchronized 一個變量 一個時刻只容許一條線程進行lock
程序次序規則
在一個程序裏面,按照程序代碼順序,書寫在前面的操做happen-before發生書寫在後面的操做
管程鎖定規則
同一把鎖,unlock happen-before lock 操做
線程中斷原則
Thread.intercupt()方法檢測到是否中斷髮生
Happens-Before 具備傳遞性,若是 A Happens-Before B,B Happens-Before C,則 A Happens-Before C
對象 init happen-before finalize()