繁体   English   中英

以下getInstance()方法有什么问题

[英]What's wrong with the following getInstance() method

我一直在学习求职面试,但发现了以下问题:

以下Singleton工厂方法getInstance()有什么问题?

public class Singleton {

    private static Singleton mySingleton;

    protected Singleton() {}

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

我知道构造函数是错误的,应该是私有的。 但是,他们在问getInstance()方法有什么问题,对我来说一切都很好,我已经看到了很多这样的示例(在多线程环境中),我还缺少什么?

原始代码的最大问题是,它是Double Check反模式的经典示例。 看起来不错,但刚刚坏了。 此处的更多信息: http : //www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

请注意,从Java 1.5开始,有一种完善的方法,同步模式或更好的静态初始化才是真正的方法。

-edit(我刚刚注意到这是在学习求职面试。如果他们显示此示例,请抽出“仔细检查”会很好。如果要求提供详细信息,我将处理一些您不太了解但可以接受的复杂Java内存问题避免再次检查的事实。祝您好运)

这看起来确实是线程安全的,但是代码比需要的复杂。 加上使用锁,会带来性能成本。 获取锁需要花费时间,并且其他试图执行该代码的线程也会被阻塞。

这两个问题可以通过使用静态初始化程序并从getInstance方法中完全删除同步来解决。 JVM将确保该语句仅执行一次。 结果是大大简化了代码,而使性能略有提高。

public class Singleton {

    private static Singleton mySingleton = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return mySingleton;
    }   
}

我想念什么?

JLS 17中描述了可能的内存影响,因此对mySingleton的写入和读取之间没有任何先发生后关系。 这是违反直觉的,但是如果您检查mySingleton不为null,则会看到错误的对象。 即在此示例中,mySingleton可以同时读写,这称为数据争用。 要修复此程序,您只需添加volatile。 根据规范,它在写入和读取之间创建事前关联。

你不是有点多余吗? 怎么样呢?

public static synchronized Singleton getInstance()
    {
        if (mySingleton == null)
            mySingleton = new Singleton();

        return mySingleton;
    }

要么...

public static synchronized Singleton getInstance()
    {
        return mySingleton==null?mySingleton=new Singleton():mySingleton;
    }

赞扬Polywhirl先生

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM