5


DefaultCache の単一のインスタンスを返すために、静的ファクトリ メソッドで以下のコードを記述しました。

public static ICache getInstance() {
   if (cacheInstance == null) {
      synchronized (ICache.class) {
         if (cacheInstance == null) {
            cacheInstance = new DefaultCache();
         }
      }
   }
   return cacheInstance;
}

同期ブロック内のcacheInstanceの2 回目の null チェックが本当に必要ですか?

4

6 に答える 6

6

ロックを取得しようとしている間に別のスレッドによって値が設定された可能性があるため、2 番目のチェックが必要です。実際、同期ブロック内に入るまで、この値を安全に見ることはできません。いつでも別のスレッドによって設定された可能性があります。

最も単純な怠惰なシングルトンは、列挙型を使用することです

public enum DefaultCache implements ICache {
     INSTANCE
}

これを行っていないので、実装を変更できると思います。

ところで: 可能な限りステートレス シングルトンのみを使用し、可能な限りすべてのステートフル オブジェクトに対して依存性注入を使用することをお勧めします。

于 2012-12-19T15:32:11.257 に答える
4

遅延初期化されたシングルトンを使用して、競合チェックの必要性を回避します。

public class Singleton {
    public static ICache getInstance() {
       return LazyCacheInitializer.INSTANCE;
    }

    private class LazyCacheInitializer {
       private static final ICache INSTANCE = new DefaultCache();
    }
}
于 2012-12-19T15:31:42.083 に答える
1

はい、それ以外の場合は 3 つ以上のインスタンスを作成できます。複数のスレッドがあるとします。最初のテストは競合状態で行われます。つまり、一部のスレッドが同時に変数を null として認識し、インスタンスを設定しようとします。2 番目のチェックがなければ、各スレッドは新しいインスタンスを作成します。

于 2012-12-19T15:34:05.877 に答える
0

が静的であると仮定すると、cacheInstance2つの可能な初期化戦略を検討する必要があります。

  • 遅延初期化:シングルトンフィールドには、最初に使用された時点でインスタンスが入力されます(例のように)。

  • (Standarad)初期化:クラスがJVMによってロードされるとすぐに、シングルトンフィールドにインスタンスが入力されます。

したがって、遅延初期化を使用する場合は、nullがないかどうかを確認する必要があります。そうしないと、nullポインタが返されます。

または、静的ブロックのフィールドを初期化することもできます。

//class declaration
 static {   
  cacheInstance = new DefaultCache(); 
 }

またはあなたがそれを宣言するのと同じ行で

private static final DefaultCache cacheInstance = new DefaultCache(); 
于 2012-12-19T15:31:06.803 に答える
0

enumPeter が投稿したようなシングルトン パターンのベース実装をいつでも使用できますが、実装はすべてクラス ローダーごとにシングルトンであることに注意してください。

Cloneableまた、インターフェースにも注意する必要があります。

于 2012-12-19T16:13:17.417 に答える
-1

これらすべてのチェックを回避するには、プライベート コンストラクターを使用します。

class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {
    }

    public static final Singleton getInstance() {
        return instance;
    }
}
于 2012-12-19T15:29:29.287 に答える