二重検査単例モードの詳細説明

1489 ワード

/**
  • 単例モード-二重チェックロック
  • @author zz


  • */public class SingleTon3 {
         private SingleTon3(){};             //       
    
         private static volatile SingleTon3 singleTon=null;
    
         public static SingleTon3 getInstance(){
    
                  //     
                 if(singleTon==null){      //   1
    
                synchronized(SingleTon3.class){  //   2
    
                           //     
    
                        if(singleTon==null){       //   3
                         singleTon=new SingleTon3();   //   4
                         }
                }
     }
     return singleTon;
    

    }注意事項:問題:if(singleTon=null)を2回判断する必要があるのはなぜですか?
    解析:最初のチェック:インスタンスを1回作成する必要がある単一インスタンスモードのため、getInstanceメソッドを後で再度呼び出すと、以前に作成したインスタンスが直接返されるため、同期メソッドのコードを実行する必要がなくなり、パフォーマンスが大幅に向上します.1回目のチェックを入れなければ、上の怠け者モードと変わらず、毎回競合ロックに行きます.
    2回目の検査:2回目の検査がなければ、スレッドt 1が1回目の検査を実行したと仮定してnullと判断し、このときt 2もCPU実行権を取得し、1回目の検査も実行し、nullと判断する.次にt 2はロックを取得し、インスタンスを作成する.このときt 1はまたCPU実行権を獲得し、前回第1回目のチェックを行ったためnull(再判断しない)となり、ロックを取得した後、直接インスタンスを作成する.結果として、複数のインスタンスが作成されます.したがって、同期コードで2回目のチェックを行い、インスタンスが空の場合は作成する必要があります.質問:なぜvolatileを追加するのですか?
    新wオブジェクトは実際には4つのステップである:a.classオブジェクトがロードされているかどうかを見て、そうでなければclassオブジェクトを先にロードし、b.メモリ空間を割り当て、インスタンスを初期化する.c.コンストラクション関数を呼び出す.d.参照にアドレスを返します.volatileを入れないと何か問題が発生しますか?
    1.2つのスレッドA,B,Bは文4に実行され、Aは文1 2に実行された.2.Bは命令が並べ替えられたため、c,dが逆転され、ちょうどdが実行され、cがまだ実行されていない間にBが掛けられた.3.このときAは文1に実行され、singletonがnullに等しくないことを発見し、まだ構築が完了していないsingletonオブジェクトを上位呼び出しに返した.