コードインスペクション: Double-Check Locking パターンの実装が誤っている可能性があります。 チェックされたフィールドへの読み取りアクセス。
次のコードを考えてみましょう。
public class Foo
{
private static volatile Foo _instance;
private static readonly object Padlock = new object();
public static Foo GetValue()
{
if (_instance != null) return _instance;
lock (Padlock)
{
if (_instance != null) return _instance;
_instance = new Foo();
_instance.Init();
}
return _instance;
}
private void Init()
{
// object initialization
}
}
Init() が Foo の状態を初期化するために使用される方法であると仮定すると、上記のコードはマルチスレッド環境では期待通りに機能しない可能性があります。
1 つのスレッドが _instance = new Foo(); を実行したがまだ _instance.Init(); を実行していない場合があります。 この時点で他のスレッドが GetValue() を呼び出すと、メソッドは _instance が null ではないことを確認し、初期化されていないインスタンスが呼び出し元に返されます。
上記のコードでこの問題を解決するには、2 つの方法があります。
最初の、最も明白なことは、 Init() の内容をプライベートコンストラクターに移動することです。
2 つ目は、初期化を非チェックの変数で行い、その後チェック済みの変数に代入することで、問題を解消します。 この方法では、 _instance は初期化済みの場合のみ not null になります。 上記の例の lock ステートメントのコードは、次のように書き換えることができます:
if (_instance != null) return _instance;
var temp = new Foo();
temp.Init();
_instance = temp;
StackOverflow に関するこの回答(英語)は、このパターンに関する他の考えられる問題と、なぜ _instance を volatile と宣言すべきかを説明します。
2026 年 6 月 12 日