ダブルチェックの代わりに・・・
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が必要なことを考えるとこっちの方がやっぱり画期的。
このパターンをしっかり覚えておかないと・・・