JVM-并发-Java 内存模型
?Java內(nèi)存模型
(1). 主內(nèi)存與工作內(nèi)存
Java內(nèi)存模型規(guī)定了所有的變量都存儲在主內(nèi)存中.
每類線程的變量的主內(nèi)存副本拷貝,線程對變量的所有操作(讀操作,賦值操作等)都必須工作內(nèi)存中進行,而不能直接讀寫主內(nèi)存中的變量.
不同的線程之間無法直接訪問對方工作內(nèi)存中的變量,線程間變量的傳遞均需要通過主內(nèi)存來完成.
(2)內(nèi)存之間額操作
主內(nèi)存與工作內(nèi)存交互,Java內(nèi)存模型定義了8種操作來完成.
a)lock(鎖定):作用于主內(nèi)存的變量,它把一個變量標識為一條線性獨占的狀態(tài).
b)ublock(解鎖):作用于主內(nèi)存的變量,它把一個處于鎖狀態(tài)的變量釋放出來,釋放后的變量才可以被其他線程鎖定.
c)read(讀取):作用于主內(nèi)存的變量,它把一個變量的值從主內(nèi)存?zhèn)鬏數(shù)骄€程的內(nèi)存中,以便隨后的load動作使用.
d)load(載入):作用于內(nèi)存的變量,它把read操作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中.
e)use(使用):作用于工作內(nèi)存中的變量,它把工作內(nèi)存中的一個變量的值傳遞給執(zhí)行引擎,每當虛擬機遇到一個需要使用變量的值的字節(jié)碼指令時將會執(zhí)行這個操作.
f)assign(賦值):作用于工作內(nèi)存中的變量,它把一個執(zhí)行引擎接收到的值賦值給工作內(nèi)存的變量,每當虛擬機遇到一個給變量賦值的字節(jié)碼指令時執(zhí)行這個操作.
g)store(存儲):作用于工作內(nèi)存的變量,它把工作內(nèi)存中一個變量的值傳遞到主內(nèi)存中,以便隨后的write操作使用.
h)write(寫入):作用于主內(nèi)存的變量,它把store操作從工作內(nèi)存中得到的變量的值放入到主內(nèi)存的變量中.
? (3)Java內(nèi)存模型規(guī)定了在執(zhí)行上述8種基本操作時必須滿足如下規(guī)則:
a) 不允許read和load,store和write操作之一單獨出現(xiàn),既不允許一個變量從主存讀取了但是工作內(nèi)存發(fā)起回寫不接受的情況出現(xiàn)
b) 不允許一個線程丟棄它的最近的assign操作,即變量在工作內(nèi)存中改變了之后必須把變量同步到主內(nèi)存
c) 不允許一個線程無原因(沒有發(fā)生過任何assign操作)把數(shù)據(jù)從線程的工作內(nèi)存同步會主內(nèi)存
d) 一個新的變量只能在主內(nèi)存中“誕生”,不允許在工作內(nèi)存中直接使用一個未被初始化的變量,換句話說就是 對一個變量實施use,store操作之前,必須執(zhí)行過了assign和load操作
e) 一個人變量在同一時刻只允許一條線程對其進行l(wèi)ock操作可以被同一條線程重復(fù)執(zhí)行多次,多次執(zhí)行l(wèi)ock后,只有執(zhí)行相同德爾unlock操作,變量才會被解鎖
f) 如果一個變量執(zhí)行l(wèi)ock操作,那將會清空工作內(nèi)存中此變量的值,在執(zhí)行引擎使用這個變量前,需要重新執(zhí)行l(wèi)oad或assign操作初始化變量的值
g) 如果一個變量事先沒有被lock操作鎖定,那就不允許對它執(zhí)行unlock操作,也不允許unlock一個被其他線程鎖定的變量
h) 對一個變量執(zhí)行unlock操作之前,必須先把此變量同步會煮主內(nèi)存(執(zhí)行store,write操作)
(4)對于volatile型變量的特殊規(guī)則:
a) 只能保證可見性
b) 禁止指令重排序優(yōu)化
(5)對long和double型變量的特殊規(guī)則:
a) Java內(nèi)存模型規(guī)定:允許虛擬機將沒有被volatile修飾的64位數(shù)據(jù)的讀寫操作劃分為兩次32位操作進行,及允許虛擬機實現(xiàn)選擇可以不保證64位數(shù)據(jù)類型的load,store,read和write這4個操作的原子性。這就是long和double的非原子性協(xié)定
(6)原子性、可見性與有序性
原子性:由Java內(nèi)存模型來直接保證的原子性變量操作包括read,load,assign,use,store和write
可見性:指當一個線程修改了共享變量的值,其他線程能夠立即得知這個修改
有序性:如果在本線程內(nèi)觀察,所有的操作都是有序的,如果在一個線程中觀察另一個線程,所有的操作都是無序的
(7)先行發(fā)生原則
先行發(fā)生時Java內(nèi)存模型中定義的兩項操作之間的關(guān)系,如果說操作A先行發(fā)生于操作B,其實就是在發(fā)生操作B之前,操作A產(chǎn)生的影響能夠被操作B觀察到。“影響”包括修改了內(nèi)存中共享變量的值,發(fā)送了消息,調(diào)用了方法等。
程序次序規(guī)則:在一個線程內(nèi),按照程序代碼順序,書寫在前面的操作先于發(fā)生在書寫在后面的操作。準確的說,應(yīng)該是控制流順序而不是程序代碼順序,因為要考慮分支、循環(huán)等結(jié)構(gòu)。
管程鎖定規(guī)則:一個unlock操作先行發(fā)生于后面對同一個鎖的lock操作。
volatile變量規(guī)則:對一個volatile變量的寫操作先行發(fā)生于后面對這個變量的讀操作,這里的“后面”是指時間上的先后順序
線程啟動規(guī)則:Thread對象的start方法先行發(fā)生于此線程的每一個動作
線程終止規(guī)則:線程中的所有操作都先于此線程的終止檢測,我們可以通過Thread.join()方法結(jié)束。THread.Alive()的返回值等手段檢到線程已經(jīng)終止執(zhí)行
線程中斷規(guī)則:對線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測到中斷事件的發(fā)生,可以通過Thread.interrupted()方法檢測到是否有中斷發(fā)生
對象終結(jié)規(guī)則:一個對象的初始化完成(構(gòu)造函數(shù)執(zhí)行結(jié)束)先行發(fā)生于它的finalize()方法的開始
傳遞性:如果操作A先行發(fā)生于操作B,操作B先行發(fā)生于操作C,那就得出操作A先行發(fā)生于操作C的結(jié)論
轉(zhuǎn)載于:https://www.cnblogs.com/lrh-xl/p/5364349.html
總結(jié)
以上是生活随笔為你收集整理的JVM-并发-Java 内存模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UE4 C++:Interface接口
- 下一篇: Java 删除文件夹