一、什么是JMM?
JMM指的是Java記憶體模型,即 Java Memory Model
- Java記憶體模型并不是一種實際存在的東西,而是一種人為形成的約定,是一種概念,
關于JMM,我們需要了解一些相關的同步約定 :
- 執行緒在解鎖前,必須將執行緒中的作業記憶體中存盤的值即時重繪到主記憶體中的共享變數!
- 執行緒在加鎖前,必須讀取主存中的最新值到作業記憶體中!
- 加鎖和解鎖是同一把鎖!
執行緒中操作的資料要從主記憶體中讀取,并備份到執行緒自己的作業記憶體中,作為副本,主存并不會主動向執行緒更新資料,
執行緒的八種記憶體互動操作:
-
- lock(鎖定):作用于主記憶體的變數,把一個變數標識為執行緒獨占狀態
- unlock(解鎖) :作用于主記憶體的變數,把一個處于鎖定狀態的共享變數釋放
- read(讀取):作用于主記憶體的變數,把一個變數的值從主記憶體傳輸到執行緒的作業記憶體中
- load(加載):作用于作業記憶體的變數,把通過read操作獲取的變數值放入作業記憶體中
- use(使用):作用于作業記憶體的變數,把作業記憶體中的變數傳輸給執行引擎,每當虛擬機遇到需要使用到變數的值,就會使用到這個指令
- assign(賦值):作用于作業記憶體的變數,把執行引擎傳輸過來的值放入作業記憶體
- store(存盤):作用于主記憶體的變數,把一個從執行緒中的作業記憶體的變數值傳送到主記憶體中,以便后續的write操作
- write(寫入):作用于主記憶體的變數,將store操作從作業記憶體獲取的變數值放入主記憶體中
JMM對以上八種記憶體操作指令做出了如下約束:
-
- read和load、user和assign、store和write、lock和unlock必須成對出現,不允許單獨操作其中一條指令
- 不允許執行緒丟棄離它最近的assign操作,即 作業記憶體中的變數值改變之后,必須告知主記憶體
- 不允許一個執行緒將沒有assign過的資料從作業記憶體同步會主記憶體
- 一個新的變數必須在主記憶體中產生,不允許作業記憶體私自初始化一個變數來作為共享變數,即 實施use 和 store操作之前 , 必須經過 load 和 assign操作
- 同一變數同一時間只允許一個執行緒對其進行lock操作;多次lock之后,必須執行相同次數的unlock對其解鎖
- 如果對一個變數進行lock操作,會清空所有作業記憶體中此變數的值, 即 每次獲得鎖的執行緒,加鎖前必須要重新讀取主記憶體中的變數值,才能提交給執行引擎進行use操作
- 如果一個變數沒有被lock,就不能對其進行unlock操作,也不能對一個被其他執行緒鎖住的變數進行unlock
- 對一個變數加鎖之前,必須把作業記憶體中的變數值同步回主記憶體

存在問題:
假設現在有一個main執行緒和一個普通執行緒,普通執行緒執行的操作是:當num為 0 時 ,一直回圈下去;此時main執行緒給num賦值為 1 ,普通執行緒并不知道num已經被修改,程式就會一直執行,不會停止!
public class VolatileDemo {
private static int num = 0;
public static void main(String[] args) {
new Thread(()->{ // 執行緒1
while (num == 0) {
}
}).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
num = 1;
System.out.println(num);
}
}
解決方法 : volatile 關鍵字
什么是volatile ?
-
volatile 是一種輕量級的同步機制,相對于synchronized來說
-
保證可見性 => JMM 主記憶體中的共享變數修改之后,會通知所有執行緒備份到各自的作業記憶體中
-
不保證原子性
-
禁止指令重排
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/289076.html
標籤:Java
上一篇:fastjson: json物件,json物件陣列,javabean物件,json字串之間的相互轉化
下一篇:【Git】pull遇到錯誤:error: Your local changes to the following files would be overwritten by merge:
