1. 程式人生 > >java 多執行緒 雙重鎖檢查

java 多執行緒 雙重鎖檢查

雙重鎖檢查

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
    }
}