(四次元新浪微博源コード学習ノート4)単例モードを実現
プライベートオブジェクトinstanceはgetInstanceで取り出し、instanceが一度だけ初期化されることを保証します.
一、マルチスレッド同期ロック
Weiciyuan0.50のTimeLineBitmapDownloaderコードはこのような書き方を採用している.
2つのスレッドが同時にインスタンスを作成したい場合、1つのスレッドがロックされた後、もう1つのスレッドが待機します.最初のスレッドがインスタンスを作成し、ロックを解除した後、2番目のスレッドがロックされ、インスタンスが作成されていることに気づき、作成されなくなりました.
しかし、ロックは時間のかかる操作であり、できるだけ避けるべきだ.
二、二重検査ロック(DCL,Double-Check Locking)
この書き方は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をうまくサポートし、このバグを解決しました.
一、マルチスレッド同期ロック
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をうまくサポートし、このバグを解決しました.