(四次元新浪微博源コード学習ノート4)単例モードを実現


プライベートオブジェクトinstanceはgetInstanceで取り出し、instanceが一度だけ初期化されることを保証します.
一、マルチスレッド同期ロック
Weiciyuan0.50のTimeLineBitmapDownloaderコードはこのような書き方を採用している.
public class TimeLineBitmapDownloader {
    private static final Object lock = new Object();
    private static TimeLineBitmapDownloader instance;
    public static TimeLineBitmapDownloader getInstance() {
        synchronized (lock) {
            if (instance == null) {
                instance = new TimeLineBitmapDownloader(new Handler(Looper.getMainLooper()));
            }
        }
        return instance;
    }
}

2つのスレッドが同時にインスタンスを作成したい場合、1つのスレッドがロックされた後、もう1つのスレッドが待機します.最初のスレッドがインスタンスを作成し、ロックを解除した後、2番目のスレッドがロックされ、インスタンスが作成されていることに気づき、作成されなくなりました.
しかし、ロックは時間のかかる操作であり、できるだけ避けるべきだ.
二、二重検査ロック(DCL,Double-Check Locking)
public class Singleton {
	private Singleton(){
	}
	private static volatile Singleton instance; //   volatile   


	public static Singleton getInstance() {
		Singleton tmp = instance; //   tmp                   ,    volatile    。
		if (tmp == null) {
			synchronized (Singleton.class) {
				tmp = instance;
				if (tmp == null) {
					instance = tmp = new Singleton();
				}
			}
		}
		return tmp;
	}
}

この書き方はvolatileを付けなければならずjava 1でなければならない.5後に成立します.
どのJavaバージョンでもvolatileを付けずにスレッドAがnewオブジェクトに実行された場合、問題が発生する可能性があります.この文には3つのプロセスが含まれています.メモリ領域を開きます.初期化データ;割り当てられたメモリ領域にinstanceを指定します.JAvaメモリモデルにはout-of-order writesのメカニズムがあり、第2ステップと第3ステップの順序は保証されていません.インスタンスドメインがメモリに完全に書き込まれていない場合、instanceはメモリ領域を指しているため、instanceはnullではない.このときスレッドBに切り替わると、スレッドBはそのままinstanceに戻りますが、このオブジェクトは完全に構築されておらず、エラーが発生します.
volatileは可視性を保証し、あるvolatileフィールドの書き込み操作happens-beforeの後に同じvolatileフィールドの読み取り操作を保証します.java1.5以降はvolatileをうまくサポートし、このバグを解決しました.