切換語言為:簡體

Java-JMM淺析

  • 爱糖宝
  • 2024-05-17
  • 2077
  • 0
  • 0

一、簡介

【概述】

JMM(JavaMemoryModel)就是Java記憶體模型,可以把JMM看作是Java定義的併發程式設計相關的一組規範,除了抽象了執行緒和主記憶體之間的關係之外,其還規定了從Java原始碼到CPU可執行指令的這個轉化過程要遵守哪些和併發相關的原則和規範,其主要目的是爲了簡化多執行緒程式設計,增強程式可移植性的。

【作用】

定義了執行緒和主記憶體之間的抽象關係:執行緒之間的共享變數儲存在主記憶體中,每個執行緒都有一個私有的本地記憶體,本地記憶體中儲存了該執行緒以讀/寫共享變數的副本。

【規定】

  1. 所有的共享變數都儲存於主記憶體。

變數指的是例項變數和類變數,不包含區域性變數,因為區域性變數是執行緒私有的,因此不存在競爭問題。

  1. 每一個執行緒還存在自己的工作記憶體,執行緒的工作記憶體,保留了被執行緒使用的變數的工作副本。

  2. 執行緒對變數的所有的操作(讀、寫)都必須在工作記憶體中完成,而不能直接讀寫主記憶體中的變數。

  3. 不同執行緒之間也不能直接訪問對方工作記憶體中的變數,執行緒間變數值的傳遞需要透過主記憶體中轉來完成。

【示例圖】

Java-JMM淺析

二、八種記憶體操作

Java-JMM淺析

  • 鎖定(lock):作用於主記憶體中的變數,將他標記為一個執行緒獨享變數。

  • 解鎖(unlock):作用於主記憶體中的變數,解除變數的鎖定狀態,被解除鎖定狀態的變數才能被其他執行緒鎖定。

  • read(讀取):作用於主記憶體的變數,它把一個變數的值從主記憶體傳輸到執行緒的工作記憶體中,以便隨後的load動作使用。

  • load(載入):把read操作從主記憶體中得到的變數值放入工作記憶體的變數的副本中。

  • use(使用):把工作記憶體中的一個變數的值傳給執行引擎,每當虛擬機器遇到一個使用到變數的指令時都會使用該指令。

  • assign(賦值):作用於工作記憶體的變數,它把一個從執行引擎接收到的值賦給工作記憶體的變數,每當虛擬機器遇到一個給變數賦值的位元組碼指令時執行這個操作。

  • store(儲存):作用於工作記憶體的變數,它把工作記憶體中一個變數的值傳送到主記憶體中,以便隨後的write操作使用。

  • write(寫入):作用於主記憶體的變數,它把store操作從工作記憶體中得到的變數的值放入主記憶體的變數中。

三、三大特徵

JMM三大特徵分別是:原子性、可見性、有序性。整個JMM實際上也是圍繞著這三個特徵建立起來的,並且也是Java併發程式設計的基礎。

1、原子性

【概述】

原子性是指一個操作是不可分割、不可中斷的,要麼全部執行成功要麼全部執行失敗。JMM只能保證對基本資料型別的變數的讀寫操作是原子性的(long和double除外)。

【示例】

int x = 1;	// 基本型別賦值操作,必定是原子性操作。
int y = x;	// 先讀取x變數的值,再進行賦值給y變數,進行了兩個操作,不能保證原子性。
x++;	// 先讀取x變數的值,再進行加1,最後再賦值給x變數,進行了三個操作,不能保證原子性。

【實現方式】

Java提供了synchronized關鍵字。在synchronized修飾的程式碼塊之間的操作都是原子性的。

2、可見性

【概述】

可見性是指所有執行緒都能看到共享記憶體的最新狀態。即當一個執行緒修改了一個共享變數的值時,其他執行緒能夠立即看到該變數的最新值。

【實現方式】

  1. volatile關鍵字:當一個共享變數被volatile關鍵字修飾時,這個變數被修改後會立即重新整理到主記憶體,保證其他執行緒看到的值一定是最新的。

  2. final關鍵字:final修飾的變數,在構造器中一旦初始化完成,如果沒有物件逸出(指物件沒有初始化完成就可以被別的執行緒使用),那麼其他執行緒都就可以看見該變數。

  3. synchronized關鍵字:執行緒進入synchronized程式碼塊後,執行緒會獲取到lock,將會清空本地記憶體,然後從主記憶體中複製共享變數的最新值到本地記憶體作為副本,執行程式碼,又將修改後的副本值重新整理到主記憶體中,最後執行緒執行unlock。

3、有序性

【概述】

有序性是指程式執行的順序按照程式碼的先後順序執行。

【實現方式】

  1. volatile關鍵字:透過在主存中加入記憶體屏障來達到禁止指令重排序,來保證有序性。

  2. synchronized關鍵字:一個變數在同一時刻只能被一個執行緒lock,並且必須unlock後,其他執行緒纔可以重新lock,使得被synchronized修飾的程式碼塊在多執行緒之間是序列執行的。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.