Java內(nèi)存模型-JMM

簡介

Java虛擬機(jī)規(guī)范中試圖定義了一種Java內(nèi)存模型(Java Memory Model,JMM)來屏蔽掉各種硬件和操作系統(tǒng)的內(nèi)存訪問差異,以實(shí)現(xiàn)讓Java程序在各種平臺(tái)下都能達(dá)到一致的內(nèi)存訪問效果。


主內(nèi)存與工作內(nèi)存

  • 主內(nèi)存-Main Memory
    Java內(nèi)存模型規(guī)定來所有變量都存儲(chǔ)在主內(nèi)存中
  • 工作內(nèi)存-Working Memory
    每條線程都有自己的工作內(nèi)存,線程的工作內(nèi)存中保存了被該線程使用到的變量的主內(nèi)存副本拷貝,線程對變量的所有操作(讀取、賦值等)都必須在工作內(nèi)存中進(jìn)行,而不能直接讀寫主內(nèi)存中的變量
    不同線程之間也無法直接訪問其他工作內(nèi)存中的變量,線程間變量值的傳遞均需要通過主內(nèi)存來完成
  • 對應(yīng)的JVM內(nèi)存區(qū)域
    主內(nèi)存對應(yīng)于Java堆中的對象實(shí)例數(shù)據(jù)部分,而工作內(nèi)存則對應(yīng)于虛擬機(jī)棧中的部分區(qū)域

內(nèi)存間交互操作

JMM中定義了8種操作方式,虛擬機(jī)實(shí)現(xiàn)時(shí)必須保證每一種操作都是原子的、不可再分的

  • lock-鎖定
    把主內(nèi)存的變量標(biāo)識(shí)為一條線程獨(dú)占的狀態(tài)
  • unlock-解鎖
    把一個(gè)處于鎖定狀態(tài)的主內(nèi)存的變量釋放,釋放后的變量才可以被其他線程鎖定
  • read-讀取
    把主內(nèi)存變量的值傳輸?shù)骄€程的工作內(nèi)存中,以便隨后的load操作使用
  • load-載入
    把read操作中從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中
  • use-使用
    把工作內(nèi)存中的一個(gè)變量的值傳遞給執(zhí)行引擎,每當(dāng)虛擬機(jī)遇到一個(gè)需要使用到變量的值的字節(jié)碼指令時(shí)就會(huì)執(zhí)行這個(gè)操作
  • assign-賦值
    把一個(gè)從執(zhí)行引擎接收到的值賦值給工作內(nèi)存的變量,每當(dāng)虛擬機(jī)遇到一個(gè)給變量賦值的字節(jié)碼指令時(shí)執(zhí)行這個(gè)操作
  • store-存儲(chǔ)
    把工作內(nèi)存中的變量的值傳送到主內(nèi)存中,以便隨后的wirte操作使用
  • write-寫入
    把store操作從工作內(nèi)存中得到的變量的值放到主內(nèi)存的變量中

原子性、可見性、有序性

JMM是圍繞著在并發(fā)過程中如何處理原子性、可見性和有序性這三個(gè)特征來建立的

原子性-Atomicity

JMM提供了lock和unlock操作來滿足這種需求,lock和unlock用戶不能直接使用但是提供了更高層次的字節(jié)碼指令monitorentermonitorexit來隱式地使用這兩個(gè)操作,反映到Java代碼就是synchronized

可見性-Visibility

可見性是指當(dāng)一個(gè)線程修改了共享變量的值,其他線程能夠立即得知這個(gè)修改,共有三種方式實(shí)現(xiàn):

  • volatile
    volatile的特殊規(guī)則保證了新值能立即同步到主內(nèi)存,以及每次使用前立即從主內(nèi)存刷新
  • synchronized
    會(huì)對變量進(jìn)行l(wèi)ock操作,對于一個(gè)變量執(zhí)行unlock操作之前,必須先把變量同步回主內(nèi)存中(執(zhí)行store、write)
  • final
    final 常量無需同步,就能被其它線程正確訪問

有序性-Ordering

如果在本線程內(nèi)觀察,所有的操作都是有序的;如果在一個(gè)線程中觀察另一個(gè)線程,所有的操作都是無序的

前半句指線程內(nèi)表現(xiàn)為串行的語意,后半句是指“指令重排序”和“工作內(nèi)存于主內(nèi)存同步延遲”

volatile和synchronized兩個(gè)關(guān)鍵字來保證線程之間操作的有序性

  • volatile
    volatile關(guān)鍵字本身就包含了禁止指令重排序的語義
  • synchronized
    synchronized是由“一個(gè)變量在同一時(shí)刻只允許一條線程對其進(jìn)行l(wèi)ock操作”這條規(guī)則獲得的,從而保證兩個(gè)同步塊只能串行地進(jìn)入

happens-before原則

happens-before(先行發(fā)生)原則,先行發(fā)生原則是JMM中定義的兩項(xiàng)操作的偏序關(guān)系,具體如下

  • 程序順序規(guī)則-Program Order Rule
    如果程序中操作A在操作B之前,那么線程中A操作將在B操作之前執(zhí)行
  • 監(jiān)視器鎖規(guī)則-Monitor Lock Rule
    unlock(退出同步方法/塊)發(fā)生在每次后續(xù)獲取同一個(gè)監(jiān)視器鎖lock之前
    例如:操作A進(jìn)行l(wèi)ock,操作B想要進(jìn)行l(wèi)ock之前,操作A必須進(jìn)行unlock
  • volatile變量規(guī)則-Volatile Variabel Rule
    volatile變量的,在每次讀取操作之前,先執(zhí)行寫入操作
  • 線程啟動(dòng)規(guī)則-Thread Start Rule
    Thread的start()方法為該線程的run()方法之前進(jìn)行的操作
  • 線程結(jié)束規(guī)則-Thread Termination Rule
    線程的所有操作都發(fā)生在線程終止之前
  • 線程中斷規(guī)則-Thread Interruption Rule
    當(dāng)一個(gè)線程在另一個(gè)線程上調(diào)用interrupt時(shí),必須在被中斷線程檢測到interrupt調(diào)用之前執(zhí)行
  • 對象終結(jié)規(guī)則-Finalizer Rule
    對象的構(gòu)造函數(shù)必須在啟動(dòng)該對象的Finalizer操作之前完成
  • 傳遞性-Transitivity
    如果操作A在操作B之前執(zhí)行,并且操作B在操作C之前執(zhí)行,那么操作A必須在操作C之前執(zhí)行

線程狀態(tài)轉(zhuǎn)換

Java中定義了5中線程狀態(tài),在任意一個(gè)時(shí)間點(diǎn),一個(gè)線程只能有且只有其中的一種狀態(tài)

  • 新建-New
    創(chuàng)建后尚未啟動(dòng)的線程處于這種狀態(tài)
  • 運(yùn)行-Runable
    Runbale包含了操作系統(tǒng)線程狀態(tài)中的Running和Ready,也就是處于此狀態(tài)的線程可能正在執(zhí)行,也有可能正在等待CPU為它分配執(zhí)行時(shí)間
  • 無限等待-Waiting
    處于這種狀態(tài)的線程不會(huì)被分配CPU執(zhí)行時(shí)間,它們需要等待被其他線程顯示的喚醒,一下方式會(huì)讓線程陷入無期限的等待狀態(tài)
    • 無timeout參數(shù)的Object.wait()
    • 無timeout參數(shù)的Thread.join()
    • LockSupport.park()
  • 限期等待-Timed Waiting
    處于這種狀態(tài)的線程也不會(huì)被分配CPU執(zhí)行時(shí)間,不過無需等待被其他線程顯式地喚醒,在一定時(shí)間之后會(huì)由系統(tǒng)自動(dòng)喚醒,一下方法會(huì)讓線程進(jìn)入限期等待狀態(tài)
    • Thread.sleep()
    • 設(shè)置timeout參數(shù)的Object.wait()
    • 設(shè)置timeout參數(shù)的Thread.join()
    • LockSupport.parkNanos()
    • LockSupport.parkUntil()
  • 阻塞-Blocked
    等待獲取到一個(gè)排他鎖,在程序等待進(jìn)入同步區(qū)域的時(shí)候,線程進(jìn)入這種狀態(tài)
  • 結(jié)束-Terminated
    已終止線程的線程狀態(tài),線程已經(jīng)結(jié)束執(zhí)行

轉(zhuǎn)換關(guān)系如圖所示:


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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