我一直在学习面试的我发现这个问题:
有什么不对下面辛格尔顿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)我缺少什么?
与原来的代码最大的问题是,它是再次确认反模式的一个典型例子。 它看起来不错,但刚刚打破。 更多关于这里: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
需要注意的是如Java 1.5的有一种方法可以巧妙的,同步的模式或更好的静态初始化真的要走的路。
-edit(我只注意到这是学习的招聘面试。拔出“双重检查”,如果他们表现出这个例子将是一件好事。如果要求的细节,我将与复杂的Java内存问题去,你没有完全理解,但接受事实上,以避免重复检查 。祝你好运)
但这似乎是线程安全的,但是代码比它需要更加复杂。 再加上使用的锁,配有性能损失。 这需要时间来获得锁,以及其他线程尝试执行该代码将被阻止。
这些2个涉及可以通过使用静态初始化并去除同步从getInstance方法完全解决的问题。 JVM将确保这一说法只执行一次。 其结果是显著简单的代码,并稍微更高性能的代码。
public class Singleton {
private static Singleton mySingleton = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return mySingleton;
}
}
我缺少什么?
可能的记忆效应中描述JLS 17 ,所以不存在之前发生写入之间关系和读取到mySingleton。 这是违反直觉的,但如果你检查了mySingleton不为空,你可以看到错误的对象。 即mySingleton在这个例子中可以写成,并在同一时间读取,它被称为数据争。 要解决这个程序,你可以再补充挥发。 根据规范它创建之前发生的写入和读取之间的关系。
是不是你有什么有点多余? 这个怎么样呢?
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先生