理解JMM記憶體模型與深入Volatile關鍵字原理

2021-10-06 20:55:47 字數 1587 閱讀 5810

一段**如下,執行緒a和執行緒b共享變數initflag。執行緒b先執行,執行緒a後執行。隨後執行緒a將initflag變為true,儲存這個操作後主記憶體中的initflag也會變為true。但是執行緒b不知道initflag已經被改變了,執行緒b會一直執行不會停下。

public

class

volatilevisibilitysample

public

void

load()

system.out.

println

(name+

":嗅探到了共享變數initflag的改變");

}public

static

void

main

(string[

] args)

,"執行緒a");

thread threadb =

newthread((

)->

,"執行緒b");

threadb.

start()

;try

catch

(interruptedexception e)

threada.

start();}}

在多執行緒的環境下,如果乙個共享變數被被volatile關鍵字修飾,那麼在乙個執行緒中改變了這個共享變數,其餘的執行緒會受到改變的通知,並從主記憶體中讀取新的值。當我們將initflag用volatile關鍵字修飾,執行緒a做的操作將會被執行緒b知道,執行緒b就會停下。實際上這個通知是通過mesi快取一致性協議實現的,其本質是乙個監聽操作,如下圖。當執行緒2將修改操作儲存到主線程時,會通過匯流排,這裡就會通知執行緒1,共享變數被改變了。

值得一提的是,在執行store和write這兩個原子操作的時候,會有乙個加鎖和解鎖的操作。

另外,在這裡再詳細說一下執行緒對共享變數的八個原子操作。如下:

多執行緒有三個原則:可見性、原子性、順序性。顯然volatile關鍵字滿足可見性,不過它不滿足原子性,見下面**:

public

class

volatileatomicsample})

; thread.

start()

;}trycatch

(interruptedexception e)

system.out.

println

(counter);}

}

理論上counter的值最後應該是10000,但是實際執行中counter會出現小於10000的情況。

說明在counter++時,有的自增操作被覆蓋了,所以volatile不滿足原子性。

另外volatile關鍵字滿足有序性,在此不做驗證。

JMM記憶體模型

依賴於jvm排程作業系統,由作業系統建立乙個核心執行緒klt,核心執行緒最終才會被cpu排程 jvm結構 jmm八大原子操作 volatitle如何保證可見性?匯流排鎖 當被volatitle修飾的變數想要修改主記憶體的資料時,會傳送一條帶有lock字首的彙編指令到匯流排上,此時它會鎖住匯流排,禁止...

JMM記憶體模型

mesi快取一致性協議 多個cpu從主記憶體讀取同乙個資料到各自的快取記憶體,當其中的乙個cpu修改了快取裡的資料,該資料會馬上同步回主記憶體,其它cpu通過匯流排嗅探機制可感知到資料的變化從而將自己快取裡的資料失效 lock unlock 匯流排加lock變成序列,效率降低 store前加lock...

java記憶體模型 JMM

1 原子性 atomicity 不可中斷的操作,即使是多個執行緒一起執行的時候,也不會被其他執行緒干擾 2 可見性 visibility 當乙個執行緒修改了某乙個共享變數的值,其他執行緒是否能夠立即知道這個修改 3 有序性 ordering 重排指令可以保證序列語義一致,但沒有義務保證多執行緒之間的...