你应该使用AtomicReference用于Singleton模式吗?

时间:2018-03-20 19:58:01

标签: java multithreading design-patterns singleton atomicreference

我遇到了AtomicReference类,并想知道这是否是创建一个可变的Singleton的好方法,可以替换为测试。

我知道双锁检查有问题所以我不想走那条路。 从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. 是否存在我不知道将其用作Singleton的问题?
  3. 什么是合理的替代方案?

1 个答案:

答案 0 :(得分:0)

  
      
  1. 是否有很大的表现?
  2.   

与任何事情一样:它取决于。

&#34;由于低到中等的争用,原子提供了更好的可扩展性;在高争用的情况下,锁可以提供更好的争用避免。&#34;

来自&#34; Java Concurrency In Practice&#34;由Goetz第15.3.2节

  
      
  1. 是否存在我不知道将其用作Singleton的问题?
  2.   

因为您没有使用锁定,所以参数lamda看起来可能同时由多个线程运行。因此,您可以创建和设置多个SingletonExample对象,但每个线程都会看到每个更新:

public static SingletonExample getInstance() {
  return sInstance.updateAndGet(u -> u != null ? u : new SingletonExample());
}
  
      
  1. 什么是合理的替代方案?
  2.   

我坚持使用简单的锁定,因为:

  1. 它按预期工作。所以你只创建一次SingletonExample。
  2. 允许您将状态变量组合在一起,您可以使用volatileAtomicReferences进行分组。