JVM內(nèi)存模型指的是JVM的內(nèi)存分區(qū)饮睬,而JAVA內(nèi)存模型是一種虛擬機(jī)規(guī)范项秉。JAVA虛擬機(jī)規(guī)范中定義了JAVA內(nèi)存模型(Java Memory Model界斜,簡(jiǎn)稱JMM)屁奏,用于屏蔽各種硬件和操作系統(tǒng)的內(nèi)存訪問(wèn)差異放钦。JMM規(guī)范了JAVA虛擬機(jī)與計(jì)算機(jī)內(nèi)存是如何協(xié)同工作的色徘,規(guī)定了一個(gè)線程如何和何時(shí)可以看到由其他線程修改過(guò)后的共享變量的值,以及必要時(shí)如何同步地訪問(wèn)共享變量操禀。
JMM規(guī)定:調(diào)用棧和本地變量存放在線程棧上褂策,對(duì)象存放在堆上:
- 一個(gè)本地變量可能是原始類型,在這種情況下颓屑,它總是“呆在”線程棧上斤寂。
- 一個(gè)本地變量也可能是指向一個(gè)對(duì)象的一個(gè)引用。在這種情況下揪惦,引用(這個(gè)本地變量)存放在線程棧上遍搞,但是對(duì)象本身存放在堆上。
- 一個(gè)對(duì)象可能包含方法丹擎,這些方法可能包含本地變量尾抑。這些本地變量仍然存放在線程棧上,即使這些方法所屬的對(duì)象存放在堆上蒂培。
- 一個(gè)對(duì)象的成員變量可能隨著這個(gè)對(duì)象自身存放在堆上再愈,不管這個(gè)成員變量是原始類型還是引用類型。
- 靜態(tài)成員變量跟隨著類定義一起也存放在堆上护戳。
- 存放在堆上的對(duì)象可以被所有持有對(duì)這個(gè)對(duì)象引用的線程訪問(wèn)翎冲。當(dāng)一個(gè)線程可以訪問(wèn)一個(gè)對(duì)象時(shí)媳荒,它也可以訪問(wèn)這個(gè)對(duì)象的成員變量抗悍。如果兩個(gè)線程同時(shí)調(diào)用同一個(gè)對(duì)象上的同一個(gè)方法驹饺,它們將會(huì)都訪問(wèn)這個(gè)對(duì)象的成員變量,但是每一個(gè)線程訪問(wèn)的都是這個(gè)成員變量在該線程中的副本缴渊。
JMM八大原子操作
關(guān)于主內(nèi)存與工作內(nèi)存之間的具體交互協(xié)議赏壹,即一個(gè)變量如何從主內(nèi)存拷貝到工作內(nèi)存、如何從工作內(nèi)存同步到主內(nèi)存之間的實(shí)現(xiàn)細(xì)節(jié)衔沼,Java內(nèi)存模型定義了以下八種原子操作來(lái)完成:
- read(讀闰蚪琛):從主內(nèi)存中讀取共享變量
- load(載入):將從主內(nèi)存中讀取到的數(shù)據(jù)寫入工作內(nèi)存
- use(使用):從工作內(nèi)存中讀取數(shù)據(jù)來(lái)進(jìn)行計(jì)算
- assign(賦值):將計(jì)算的結(jié)果重新賦值到工作內(nèi)存中
- store(存儲(chǔ)):將工作內(nèi)存中的數(shù)據(jù)寫入主內(nèi)存
- write(寫入):將store到主內(nèi)存中的數(shù)據(jù)賦值給主內(nèi)存中的共享變量
- lock(鎖定):將主內(nèi)存中的共享變量加鎖,標(biāo)識(shí)為線程獨(dú)占狀態(tài)
- unlock(解鎖):將主內(nèi)存中的共享變量解鎖指蚁,解鎖后其他線程可以鎖定該變量
一個(gè)線程對(duì)于共享變量值的修改菩佑,會(huì)在這個(gè)線程運(yùn)行結(jié)束前同步回主內(nèi)存中,具體同步的時(shí)間點(diǎn)不固定凝化,可能在線程運(yùn)行過(guò)程中稍坯,也可能在線程快要運(yùn)行結(jié)束時(shí)。如果這個(gè)共享變量被volitail關(guān)鍵字修飾搓劫,則會(huì)立刻同步回主內(nèi)存瞧哟,并將其他線程中的共享變量副本置為失效。
References
https://zhuanlan.zhihu.com/p/29881777
https://www.cnblogs.com/Courage129/p/14402519.html