使用Singleton模式的多线程环境中是否存在任何问题?

时间:2011-11-30 06:58:22

标签: java multithreading design-patterns singleton

我已经实现了Singleton类,如下所示:

public class Singleton {

    private static  Singleton instance = null;


    private Singleton() { 
    }

private synchronized static void createInstance() {
    instance = new Singletone();
}


    public static Singleton getInstance() {
        if(instance == null){
            createInstance();
        }
        return instance;
    }

}

但我想知道它是否是单例的正确实现。 多线程环境中是否有任何问题。

7 个答案:

答案 0 :(得分:7)

public enum Singleton {
    INSTANCE;
    private int val;

    public int getVal() {
        return val;
    }
}

用法:

Singleton.INSTANCE.getVal();

这是Java版本的完美单例> 5.0你有枚举支持。

Joshua Bloch的Effective Java也提到过。有关它的博客文章:Enum Singleton

<强>更新
此外,只有当您100%确定需要单身时,请使用单身人士!它会破坏代码的可测试性!但是你无法避免在工厂里出现这种情况 但请不要滥用它,在实际需要的地方使用它。了解它的用途。

答案 1 :(得分:5)

您的实施几乎是正确的。问题是它不是线程安全的。 2个单独的线程可以同时输入getInstance(),检查该实例是否为null,然后创建2个类的实例。这是修复:

public static synchronized Singletone getInstance() {
    if(instance == null){
        createInstance();
    }
    return instance;
} 

请注意synchronized字。

答案 2 :(得分:2)

除了上面的枚举之外,我遇到的最佳机制称为静态初始化。有了这个,你就依赖于Java内存模型的保证,所以它始终有效。以下是来自an answer to a different question的片段,用于说明这一点:

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

第一次调用SingletonHolder时,将创建具有Singleton实例化的SingletonHolder.INSTANCE类对象。

Java内存模型保证静态代码(new Singleton())只能由一个线程执行。因此没有双重检查锁定(这不起作用),也没有不必要的同步。所有后续调用都将获取该实例。

答案 3 :(得分:0)

这是单例模式的正确实现,尽管您实际上并不需要createInstance方法;你可以在getInstance中内联这个内容。此外,它拼写为“Singleton”,最后没有“e”。

假设您可以在多线程环境中创建问题。如果两个帧指针同时输入getInstance,则首先输入的那个可以获得Singleton的实例,而第二个可以获得另一个实例。

这取决于你如何使用它。如果在设置线程之前使用单例,则没有问题。如果这是一个问题,您可以考虑首先初始化单例。您也可以使用方法声明中的synchronized关键字来解决此问题。

答案 4 :(得分:0)

Singleton不是线程安全的。出于这个原因,引入了Double-checked Locking

从Java SE 5及更高版本开始,您可以volatile您的静态实例。当多个线程运行时,Java VM将知道如何正确处理Singleton。

更多关于Double-checked locking

答案 5 :(得分:0)

对于延迟初始化实现,这是你的情况,应该为了线程安全而同步getInstance()方法。

public static synchronized Singleton getInstance()

或者您可以在类加载时初始化它,该加载时已经是线程安全的。

private static  Singleton instance = new MySingleton(); 

答案 6 :(得分:-1)

您的实施似乎没问题。单个JVM中的多线程对于那种单例问题不是问题,但它会在集群(两个或更多JVM)中引起问题。

请参阅http://java.sun.com/developer/technicalArticles/Programming/singletons/了解这些问题。

哦,这是单身人士,不是单身人士。 :)