02_實現Singlnton模式

1. 雙重加鎖
public class Singlnton{

    private static volatile Singlnton instance;
    
    private Singlnton(){
        
    }
    
    public static Singlnton getInstance(){ // 1
        if(instance==null){ // 2
            synchronized(Singlnton.class){ // 3
                if(instance==null){ // 4
                    instance = new Singlnton(); // 5
                }
            }
        }
        return instance;
    }
    
}
  • volatile關鍵字的作用?
  • 雙重檢鎖單例模式在CPU的工作流,主要分爲三步,1:分配內存對象空間。2:初始化對象。3:設置instance執行剛纔分配的內存地址,注意jvm和cpu優化會指令重排,上面順序會變成1-3-2,單線程環境下,此順序是沒有問題,2和3 前後沒有依賴性,但是在多線程情況下會有這種情況,當線程A在執行第5行代碼時,B線程進來執行到第2行代碼。假設此時A執行的過程中發生了指令重排序,即先執行了1和3,沒有執行2。那麼由於A線程執行了3導致instance指向了一段地址,所以B線程判斷instance不爲null,會直接跳到第6行並返回一個未初始化的對象。volatile保持指令的有序性,能夠有效禁止指令重排序。
2. 靜態內部類
public class Singlnton{

    private Singlnton(){

    }

    private static class SinglntonHolder{
        private static Singlnton INSTANCE = new Singlnton();
    }

    public static Singlnton getInstance(){
        return SinglntonHolder.INSTANCE;
    }

}

3. Kotlin中的單例模式
class Singlnton{
    
    companion object{
        val instance : Singlnton by lazy { Singlnton() }
    }
    
}
  • lateinit和by lazy的區別:
  • lateinit只能用於修飾變量var,不能用於可空的屬性和Java的基本類型。
  • lateinit可以在任何位置初始化並且可以初始化多次。
  • lazy()只能用於修飾常量val,並且lazy()是線程安全的。
  • lazy()是一個函數,可以接受一個Lambda表達式作爲參數,第一次調用時會執行Lambda表達式,以後調用該屬性會返回之前的結果。
  • lazy()源碼分析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章