daybreaksnow's diary

私を私と呼びたい

[Java]インスタンスの遅延初期化時の注意

シングルトンインスタンスを遅延初期化するときに以下のようなコードを書くと、Javaでは意図しない動作(複数回newされる)を引き起こすことがある。
参考:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

public class Hoge{
  private Helper helper; 

  public Helper getHelper(){
    if(helper == null){
       synchronized(this){
           if(helper == null){
               helper = new Helper();
           }
       }
    }
    return helper;
  }
}

理由は、helperフィールドへの代入が行われた後、その値が即座に読み取られることが保障されないから、とのこと。
上記コードはhelperフィールドにvolatile修飾子をつけることで対応できる。(ただしJDK1.5以降のみ)
volatile修飾子をつけると別スレッドからでも最新の値が見えるようになる。

なお、もしhelperクラスがImmutable(全てfinal)ならば、volatile修飾子をつけずとも、上記のコードで正しく動作する。