这个在面试美团时让手写了,并说出如何理解,差点忘了
public static Singleton getInstance()
{
if (instance == null) //1
{
synchronized(Singleton.class) { //2
if (instance == null) //3
{
instance = new Singleton(); //4
}
}
}
return instance;
}
第一个if 保证对象为空才会有资格竞争锁 ,保证了代码的效率
第二个if 保证如果其他线程已经创建出了,就不会再new ,直接返回之前已经创建好的对象,保证了单例
上面的代码存在一定的问题,问题的原由在第4句代码 instance =new Singleton()
这句代码可以分解为三句伪代码:
memory = allocate(); //1:分配对象的内存空间
ctorInstance(memory); //2:初始化对象
instance = memory; //3:设置instance指向刚分配的内存地址
上述的第2句代码和第3句代码可能会重排序
如果重排序,有线程将可能会拿到未被初始化的对象
解决办法:用volatile修饰instance
private volatile static Singleton instance;
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) {
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
volatile在多线程下禁止三句伪代码的重排序
转载请注明:汪明鑫的个人博客 » 单例模式之double check
说点什么
1 评论 在 "单例模式之double check"
[…] 单例模式之double check […]