java基礎之Synchronized、volatile
阿新 • • 發佈:2018-12-22
Synchronized
Synchronized語義
- 進入同步塊之前,先清空工作記憶體中的共享變數,從主記憶體中載入
- 解鎖之前(出去同步程式碼塊之前),必須把工作記憶體的共享變數 同步 到主記憶體**
Synchronized用法
-
物件鎖
-
類鎖
synchronized 影響記憶體的過程
- 一個執行緒在獲取到監視器鎖以後才能進入 synchronized 控制的程式碼塊
- 進入程式碼塊以後,該執行緒對於共享變數的快取就會失效,synchronized 程式碼塊中對於共享變數的讀取需要從主記憶體中重新獲取,也就能獲取到最新的值
- 退出synchronized 程式碼塊的時候的,會將該執行緒寫緩衝區中的資料刷到主記憶體中,所以說synchronized 具有可見性。
執行緒 a 對於進入 synchronized 塊之前或在 synchronized 中對於共享變數的操作,
對於後續的持有同一個監視器鎖的執行緒 b 可見
volatile
volatile 保證了可見性、禁止重排序,但是不能保證執行緒安全
volatile語義
- 使用volatile時,必須重新從主記憶體中載入,並且read、load是連續的
- 修改volatile修飾的變數後,必須立即同步主記憶體,並且store、write是連續的
volatile適用場景
- 很明顯,計數器不適用,volatile 並不能保證原子性
- Boolean的狀態標誌
- 比如溫度檢測系統,一個執行緒定時從硬體讀取溫度,保證其他執行緒總是能拿到最新的問題
- 一次性安全釋出(one-time safe publication),雙重檢查鎖定(double-checked-locking)問題
雙重檢查形式的單例模式為什麼需要使用 volatile
private static SingletonTest instance = null;
private int num;
private SingletonTest() {
this.num = 1;
}
public static SingletonTest getInstance() {
if (instance == null) { // 1. 第一次檢查
synchronized (SingletonTest.class) { // 2
if (instance == null) { // 3. 第二次檢查
instance = new SingletonTest(); // 4
}
}
}
return instance;
}