一丶工作內(nèi)存和主內(nèi)存
java內(nèi)存模型,簡稱JMM(Java Memory Model),個人對于JMM理解是:JVM屏蔽了操作系統(tǒng)對于物理內(nèi)存訪問的復(fù)雜性怕膛,目的從軟件設(shè)計角度呈現(xiàn)出的一種內(nèi)存訪問的邏輯視圖。也就是JMM是JVM為軟件工程師提供的一系列內(nèi)存訪問的邏輯規(guī)則,理解并合理使用這些規(guī)則就能正確訪問內(nèi)存素挽,至于底層和物理內(nèi)存直接交互動作已經(jīng)被透明化了,無須關(guān)心狸驳。下圖是JMM內(nèi)存模型視圖预明,是內(nèi)存訪問規(guī)則的基礎(chǔ)。
JMM視圖
-
主內(nèi)存:
主內(nèi)存是線程公有的耙箍,是所有線程都能訪問的內(nèi)存區(qū)域撰糠,一般對應(yīng)于java內(nèi)存布局中的堆區(qū)。 -
工作內(nèi)存
工作內(nèi)存是線程私有的辩昆。一般對應(yīng)于JVM虛擬機棧阅酪,以及本地方法棧 -
工作內(nèi)存和主內(nèi)存之分
從邏輯上看,如果沒有主內(nèi)存和工作內(nèi)存的區(qū)分,只有一整塊的內(nèi)存术辐,似乎也并無不妥砚尽。那么區(qū)分主內(nèi)存和工作內(nèi)存的意義何在?馮諾依曼的計算機體系結(jié)構(gòu)
CPU曼振,高速緩存几迄,內(nèi)存之間關(guān)系
二丶工作內(nèi)存和主內(nèi)存之間的交互規(guī)則
工作內(nèi)存和主內(nèi)存之間協(xié)同工作才是JMM的核心部分荠商。從上文描述中可以知道,工作內(nèi)存是主內(nèi)存部分內(nèi)容的拷貝抒寂,在多線程環(huán)境中结啼,可能存在多份主內(nèi)存的拷貝。CPU是直接操作工作內(nèi)存屈芜,最后將工作內(nèi)存同步到主內(nèi)存郊愧,這個過程會造成各個工作內(nèi)存具備不一致性朴译。為了在多線程環(huán)境下能實現(xiàn)工作內(nèi)存中一致性,JMM定義了工作內(nèi)存和主內(nèi)存之間的交互操作属铁,總共有8個原子性的交互操作
-
lock
鎖操作眠寿,如果線程對內(nèi)存中某個變量進行了lock,在同一時間將禁止其他所有線程對主內(nèi)存中該變量進行讀取操作焦蘑。線程對應(yīng)的工作內(nèi)存和主內(nèi)存之間禁止交互盯拱。 -
unlock
unlock 操作在lock操作之后執(zhí)行。這是釋放鎖操作例嘱,將放開線程對工作內(nèi)存中變量的讀取操作狡逢。放開線程對應(yīng)的工作內(nèi)存和主內(nèi)存之間的交互。lock操作和unlock操作是成對出現(xiàn)的拼卵,執(zhí)行多少次lock操作奢浑,就要執(zhí)行相應(yīng)次數(shù)的unlock操作才能完全釋放。 -
load
load操作腋腮,是指將主內(nèi)存中某個變量的值加載到工作內(nèi)存中雀彼,可以看成一次內(nèi)存轉(zhuǎn)移操作。 -
read
read操作和load操作成對出現(xiàn)即寡,邏輯上出現(xiàn)在load操作之后徊哑,該操作將轉(zhuǎn)移到工作內(nèi)存中的變量值具體復(fù)制給某個變量。read可看成是發(fā)生在工作內(nèi)存之中的變量初始化操作聪富,load是工作內(nèi)存和主內(nèi)存之間的拷貝工作莺丑,兩者配合完成一次變量讀取操作。 -
use
CPU使用工作內(nèi)存中變量需要執(zhí)行use操作墩蔓,是定義在工作內(nèi)存中的一種操作 -
assign
賦值操作窒盐,顯而意見,如果發(fā)生變量賦值操作钢拧,將執(zhí)行該原子原子操作,是定義在工作內(nèi)存中的操作炕横。 -
store
該操作和load操作是對應(yīng)的操作源内,完成工作內(nèi)存中內(nèi)容向主內(nèi)存中內(nèi)容的轉(zhuǎn)移。 -
write
writer操作邏輯上發(fā)生在store操作之后份殿,完成對主內(nèi)容變量的回寫膜钓。store操作和write操作是load和read操作的對稱操作。
JVM定義的上述八種操作均是原子的卿嘲,是最小操作單位颂斜,不可分割。除此之外拾枣,上述八個操作并不是孤立的沃疮,而是相互聯(lián)系的盒让,它們之間的操作必須符合下述規(guī)則:
(1) 對主內(nèi)存中某個變量執(zhí)行l(wèi)ock操作,將會清空工作內(nèi)存中該變量值司蔬。對變量執(zhí)行unlock操作之前邑茄,必須將其同步到主內(nèi)存中(store,write)。
(2)工作內(nèi)存中的變量如未經(jīng)過assgin操作俊啼,那么不允許同步到主內(nèi)存中肺缕。
(3)load和read操作必須順序執(zhí)行,但不一定需要連續(xù)執(zhí)行授帕。store和write操作也必須順序執(zhí)行同木,但不一定需要連續(xù)執(zhí)行。上述兩對操作必須形成閉環(huán)跛十,不能只有l(wèi)oad操作而沒有read操作彤路。
上述的八個原子操作和相應(yīng)的交互規(guī)則就是JVM對內(nèi)存的訪問規(guī)則,掌握和理解這些規(guī)則對開發(fā)正確的多線程程序十分重要