2

私はAtomicReferenceクラスに出くわし、これが変更可能でテスト用に置き換えることができるシングルトンを作成する良い方法になるかどうか疑問に思っていました。

二重ロックのチェックに問題があることはわかっているので、そのルートには行きたくありませんでした。 JDK 1.5 の時点で修正されました ( https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html )
また、シングルトンを初期化するのではなく、遅延してインスタンス化することをお勧めします。たとえば、テスト中はデフォルトのクラスを使用したくありませんSimpleExampleが、場合によっては、作成にコストがかかるか、特定の環境で問題が発生します。依頼前に交換していただけると助かります。

public class SingletonExample {

  private static AtomicReference<SingletonExample> sInstance = new AtomicReference<>();

  private SingletonExample() {
  }

  public static SingletonExample getInstance() {
      return sInstance.updateAndGet(u -> u != null ? u : new SingletonExample());
  }

  @VisibleForTesting
  static void setInstance(SingletonExample singletonExample) {
      sInstance.set(singletonExample);
  }
}

ここに私の質問があります:

  1. 大きなパフォーマンス ヒットはありますか?
  2. シングルトンとして使用することに気付いていない問題はありますか?
  3. 合理的な代替手段は何ですか?
4

1 に答える 1

0
  1. 大きなパフォーマンス ヒットはありますか?

何でもそうですが、状況によります。

「競合が低から中程度の場合、アトミックはより優れたスケーラビリティを提供します。競合が高い場合、ロックはより優れた競合回避を提供します。」

Goetz セクション 15.3.2 による「Java Concurrency In Practice」より

  1. シングルトンとして使用することに気付いていない問題はありますか?

ロックを使用していないため、パラメーター lamda は複数のスレッドで同時に実行できるように見えます。したがって、複数の SingletonExample オブジェクトを作成および設定できますが、各スレッドは各更新を確認します。

public static SingletonExample getInstance() {
  return sInstance.updateAndGet(u -> u != null ? u : new SingletonExample());
}
  1. 合理的な代替手段は何ですか?

次の理由から、単純なロックに固執します。

  1. 意図したとおりに機能します。したがって、SingletonExample は 1 回だけ作成します。
  2. volatileまたはではできない状態変数のグループ化を可能にしますAtomicReferences
于 2018-03-21T18:04:34.870 に答える