java 多執行緒 雙重鎖檢查
阿新 • • 發佈:2018-11-09
雙重鎖檢查
public class User { private static User user; public static User getInstance() { if (user == null) { // 1:第一次檢查 synchronized (User.class) { // 2:加鎖 if (user == null) { // 3:第二次檢查 user = new User(); //4 } } } return user; // 10 } }
上面的程式碼是一個簡單的單例模式 ,但是這個程式碼是有問題的 問題在於第4步
java 建立一個物件需要
1:分配物件的記憶體空間
2:初始化物件
3:設定物件指向剛分配的記憶體地址
但是處理器可能會"重排序" 為
1:分配物件的記憶體空間
3:設定物件指向剛分配的記憶體地址
2:初始化物件
如果執行緒A 進入 getInstance() 然後 進入syn 然後new User();new User 被重排序,當執行到設定物件記憶體地址時 , 執行緒B 進入 getInstance() 判斷 user不為null 返回user 此時執行緒A 還沒有完成初始化物件 而執行緒B已經返回了 user 所以 會有問題。
如果解決呢 可以用 volatil 關鍵字解決 : volatile 具有可見性 用volatile修飾的變數 一個執行緒修改後立刻對所有執行緒可見。
public class User { private volatile static User user; // 加 volatile 解決問題 public static User getInstance() { if (user == null) { // 1:第一次檢查 synchronized (User.class) { // 2:加鎖 if (user == null) { // 3:第二次檢查 user = new User(); //4 } } } return user; // 10 } }