Shammer's Philosophy

My private adversaria

ダブルチェックの代わりに・・・

JSR 133に、Javaのメモリモデルについての情報がある。
そして、この情報は和訳されている様子。

  http://www.javareading.com/bof/cookbook-J20060917.html

reorderとか、volatileの話など、かなりマニアックな情報だ。
さらに、FAQの話もある。先のダブルチェックはNGという話もここに情報が・・・

  http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html

このようにすれば、複数スレッドからアクセスされても安全な実装になるらしい。

public class InitializeOnDemandHolder {
  private static class LazyHolder {
    public static InitializeOnDemandHolder singleton = new InitializeOnDemandHolder();
  }
  public static InitializeOnDemandHolder getInstance() {
    return LazyHolder.singleton;
  }
  private InitializeOnDemandHolder(){
  }
  private Object object = new Object();
  public getObject(){
    return object;
  }
}

考えましたなぁ・・・
この実装では、synchronizedやvolatileを使っていない。すなわち、パフォーマンスの低下はない。
private static なインナークラスを持ち、その中で自分を初期化している。
privateであるため、外部から直接アクセスされることはない。
staticなのでInitializeOnDemandHolderクラスがClassLoadされた際に、LazyHolderは初期化される。
ClassLoadの時点で行われるということは、そのJVM内で基本的には一度しか呼ばれないことを意味する。
この一度しか呼ばれないタイミングをうまく活用してSingletonを実現する実装、というところか。

ダブルチェックでは、二度synchronizedが必要なことを考えるとこっちの方がやっぱり画期的。
このパターンをしっかり覚えておかないと・・・