JAva単例モード完璧版書き方

5874 ワード

必要に応じて、単一のdemoを記録します.
public class SingletonDemo {

    private static volatile SingletonDemo instance = null;
    private SingletonDemo(){
    	//     ,         
        System.out.println(Thread.currentThread().getName()+"\t       SingletonDemo");
    }

    //      (DCL Double Check Lock)
    public static SingletonDemo getInstance(){
        if(instance == null){
            synchronized (SingletonDemo.class){
                if(instance == null){
                    instance = new SingletonDemo();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        for(int i = 1 ; i <= 10 ;i++) {
            new Thread(()->{
                SingletonDemo.getInstance();
            },String.valueOf(i)).start();
        }
    }
}

注意:private static volatile SingletonDemo instance=null;ここでvolatileキーワードは、追加しないと、コードを実行し、結果は正しいようです.しかし、実際にN回実行した後、異常が発生する可能性があります.volatileを付けないため、instance=new SingletonDemo();この行はシステムによって3行(疑似コード):1に分割されます.memory = allocate;//オブジェクトのメモリ領域2を割り当てる.instance(memory);//オブジェクトの初期化;3.instance = memory;//Instanceが割り当てたばかりのメモリアドレスを指すように設定します.instance!=null; ステップ2および3にはデータ依存関係はなく、命令の並べ替え前後にかかわらず、単一スレッドでの実行結果は同じであるため、このような並べ替え最適化は許容される.1.memory = allocate;//オブジェクトのメモリ領域3を割り当てる.instance = memory; 2.instance(memory);//オブジェクトの初期化;しかし、マルチスレッドでは、1つのスレッドがinstanceにアクセスするのはnullではありませんが、instanceはまだ初期化が完了していない可能性があり、スレッドのセキュリティの問題をもたらします.だからvolatileキーワードを追加して、命令の再ソートを禁止しなければなりません.