『増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編』に載っているデザインパターンを Groovy/GPars で書こうシリーズ、今回は Double-checked Locking パターン。 このパターンは、複数のスレッドからアクセスされる可能性のあるフィールドの遅延初期化 (lazy initialization) を行いたいときに用います。 static フィールドの遅延初期化は Initialization On Demand Holder パターン(次回やる予定)を用いるのが最善とされてますが、インスタンスフィールドの場合には使えないので、少々込み入っているこの Double-checked Locking パターンが必要です。 マルチスレッド・プログラミングの書籍には大抵書いてますが、このパターンは Java 1.4 以前で用いると予期せぬ初期化がされる可能性があります。
参考 URL
サンプル・コード その1
Double-checked Locking パターンの典型的なコード。 『Effective Java 第2版 (The Java Series)』を参考にしています:
class MyClass { private volatile MyField field MyField getField(){ MyField result = this.field if(result == null){ synchronized(this){ result = this.field if(result == null)this.field = result = new MyField() } } return result } } class MyField{}
- フィールドの volatile 宣言を忘れずに!
- ローカル変数 result は使わなくても動作しますが、使った方がパフォーマンスが向上するそうです(既に初期化が完了している場合のメソッド呼び出しに於いて)。
- volatile 宣言されているフィールドの読み込みは、最近の JVM ではほとんどコストなく実行できるそうなので、上記のコードは getter メソッド自体を synchronized にするよりもパフォーマンスがよいそうです(試してませんが)。
サンプル・コード その2
次は Groovy の @Lazy アノテーションを用いたサンプル。
class MyClass { @Lazy volatile MyField field = new MyField() }
こちらでも volatile 宣言を忘れずに。 @Lazy アノテーションを付加することによってローカル AST 変換が行われ、「サンプル・コード その1」のようなコードに書き換えられます(詳しくは @Lazy アノテーションのドキュメントを参照のこと)。 フィールドの初期化に処理が必要な場合は「クロージャ+ () 」を用います:
class MyClass { @Lazy volatile MyField field = { /* インスタンスを生成する処理 */ }() }
増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編
- 作者: 結城浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2006/03/21
- メディア: 大型本
- 購入: 15人 クリック: 287回
- この商品を含むブログ (199件) を見る
- 作者: 関谷和愛,上原潤二,須江信洋,中野靖治
- 出版社/メーカー: 技術評論社
- 発売日: 2011/07/06
- メディア: 単行本(ソフトカバー)
- 購入: 6人 クリック: 392回
- この商品を含むブログ (152件) を見る