Java プログラムメモ


トップ

Singleton 作成時のダブルチェック

Singleton 作成時のダブルチェックロッキングは動作が保証されていません。 マルチスレッド絡みのバグなので、障害が発生しても非常に見つけにくい物です。

ダブルチェックロッキングを使用した例

public static SingletonTest getInstance() { if (instance_ == null) { synchronized (SingletonTest.class) { ・・・・・・1 if (instance_ == null) ・・・・・・2 instance_ = new SingletonTest(); ・・・・・・3 } } return instance_; }

期待動作

ダブルチェックロッキングを利用してる人の期待している動作は
スレッド 1 スレッド 2
getInstance() に入る
instance_ が null の為 1 に入る
切り替え → getInstance() に入る
instance_ が null の為 1 に入るがブロックされる
2 でまだ instance_ が null の為 3 で new して instance_ に代入 ← 切り替え
return でインスタンスの取得
切り替え → 1 でロックを取得して、2 の評価を行う
instance_ は null でない為スレッド 1 と同じインスタンスの取得

実際にはこのように動作しない可能性があります。どこが問題かと言うと、3 のインスタンスの生成部で、 Java のメモリー・モデルでは、SingletonTest のコンストラクターが実行される前に、 instance_ が null でなくなる可能性があります。

バグが顕著化する場合の動作

スレッド 1 スレッド 2
getInstance() に入る
instance_ が null の為 1 に入る
3 で instance_ を null でなくするが、コンストラクタは未実行
切り替え → getInstance() に入る
instance_ が null でない為初期化されていないインスタンスを取得する。
Error 発生
コンストラクタを実行して初期化する。 ← 切り替え

Java で Singleton を実現する

Singleton を作成するときはこんな感じで書くと正常に動作します。

public final class SingletonTest { private static SingletonTest instance_ = new SingletonTest(); public static SingletonTest getInstance() { return instance_; } private SingletonTest() { } }


SEO [PR] おまとめローン Windows7 冷え性対策 動画 掲示板 レンタルサーバー ライブチャット SEO