JetBrains Rider 2026.1 Help

コードインスペクション: 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 に関するこの回答(英語)は、このパターンに関する他の考えられる問題と、なぜ _instancevolatile と宣言すべきかを説明します。

2026 年 6 月 12 日