有什么不对以下getInstance()方法(What's wrong with the f

2019-10-21 06:03发布

我一直在学习面试的我发现这个问题:

有什么不对下面辛格尔顿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()方法,一切都看起来好像没什么问题,我已经看到了很多的例子像这样的(在多线程environement)我缺少什么?

Answer 1:

与原来的代码最大的问题是,它是再次确认反模式的一个典型例子。 它看起来不错,但刚刚打破。 更多关于这里: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

需要注意的是如Java 1.5的有一种方法可以巧妙的,同步的模式或更好的静态初始化真的要走的路。

-edit(我只注意到这是学习的招聘面试。拔出“双重检查”,如果他们表现出这个例子将是一件好事。如果要求的细节,我将与复杂的Java内存问题去,你没有完全理解,但接受事实上,以避免重复检查 。祝你好运)



Answer 2:

但这似乎是线程安全的,但是代码比它需要更加复杂。 再加上使用的锁,配有性能损失。 这需要时间来获得锁,以及其他线程尝试执行该代码将被阻止。

这些2个涉及可以通过使用静态初始化并去除同步从getInstance方法完全解决的问题。 JVM将确保这一说法只执行一次。 其结果是显著简单的代码,并稍微更高性能的代码。

public class Singleton {

    private static Singleton mySingleton = new Singleton();

    private Singleton() {}

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


Answer 3:

我缺少什么?

可能的记忆效应中描述JLS 17 ,所以不存在之前发生写入之间关系和读取到mySingleton。 这是违反直觉的,但如果你检查了mySingleton不为空,你可以看到错误的对象。 即mySingleton在这个例子中可以写成,并在同一时间读取,它被称为数据争。 要解决这个程序,你可以再补充挥发。 根据规范它创建之前发生的写入和读取之间的关系。



Answer 4:

是不是你有什么有点多余? 这个怎么样呢?

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先生



文章来源: What's wrong with the following getInstance() method