为什么单件设计模式不适合多线程环境?

时间:2016-06-03 20:23:12

标签: design-patterns singleton

使用Singleton模式进行静态初始化 - 它可以解决多线程环境问题,而不是明确地去锁定块。

2 个答案:

答案 0 :(得分:1)

编写线程安全的单例类有很多种方法。我们来看看。

创建单身时,有三件事你可能会关心:

  1. 线程安全
  2. 可以通过
  3. 延迟加载
  4. 处理构造函数中引发异常的能力。
  5. 以下最原生的实现:

    public class Singleton {
         private static Singleton instance;
    
         private Singleton() {}
    
         public synchronized static Singleton getInstance() {
              if (instance == null) {
                   instance = new Singleton();
              }
              return instance;
         }
    }
    

    这里唯一的缺点是,当多个线程同时调用getInstance()时,每次调用getInstance()时都会进行同步,吞吐量会受到影响。

    好的,下一个解决方案是:

    public class Singleton {
        private static Singleton instance = new Singleton();
    
        private Singleton() {
        }
    
        public synchronized static Singleton getInstance() {
            return instance;
        }
    

    它的线程安全,吞吐量很好,但我们丢失了延迟加载(实例将在加载类时创建,但不会在第一次调用getInstance()时创建)并且我们无法处理构造函数的异常。

    下一步:

    public class Singleton {
        private Singleton() {}
    
        private static class SingletonHolder {
            private final static Singleton instance = new Singleton();
    
        }
    
        public static Singleton getInstance() {
            return SingletonHolder.instance;
        }
    }
    

    这个实现是我最喜欢的。它的线程安全,吞吐量是完美的,它是懒惰的。唯一的缺点是您仍然无法处理构造函数中的异常。否则,请使用它。

    如果从构造函数处理异常很重要,请使用双重检查锁定:

    class Singleton {
        private static volatile Singleton instance;
    
        private Singleton() {}
        public Singleton getInstance() {
            if (instance == null) {
                synchronized(this) {
                    if (instance == null)
                        instance = new Singleton();
                }
            }
            return instance;
        }
    }
    

    请注意,由于易失性的关键字语义,它只能在Java 5之后使用。

答案 1 :(得分:0)

您可以实现线程安全单例,但如果对象被不同的线程大量使用,则需要付出代价。 Thread Safe C# Singleton Patternhttp://csharpindepth.com/Articles/General/Singleton.aspx#performance