從萌新的角度理解java內(nèi)存模型

一丶工作內(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)
    上圖是耳熟能詳?shù)鸟T諾依曼體系結(jié)構(gòu),現(xiàn)代計算機是基于馮諾依曼體系上發(fā)展起來的。該體系有兩個關(guān)鍵的組成就是存儲器和CPU(運算器和控制器)。其中存儲器則是我們所討論的物理內(nèi)存。CPU和內(nèi)存之間的IO操作是存在瓶頸的,內(nèi)存的操作速度遠遠小于CPU的運算速度。在CPU和內(nèi)存協(xié)同工作的場景中,CPU以較短的時間完成數(shù)值計算后,需要花較長的時間等待內(nèi)存讀取操作,造成了CPU運算資源的浪費。于是,位于CPU和內(nèi)存之間的高速緩存應(yīng)運而生。
    CPU,高速緩存,內(nèi)存之間關(guān)系
    在引入了高速緩存之后,CPU會將運算所需要的數(shù)據(jù)一次性的加載到高速緩存中,高速緩沖具備比內(nèi)存更快的存取速度。CPU和高速緩存之間配合大大提高了CPU資源的利用率。此時在看工作內(nèi)存和主內(nèi)存關(guān)系,從邏輯上,高速緩存對應(yīng)工作內(nèi)存,每個線程分配到CPU時間片時,獨自享有高速緩存的使用能力。主內(nèi)存對應(yīng)存儲的物理內(nèi)存。特別注意,這只是邏輯上的對等關(guān)系,物理的上具體對應(yīng)關(guān)系十分復(fù)雜,這里不討論。

二丶工作內(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ā)正確的多線程程序十分重要
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容