[英]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.