您的位置:首页 > 职场人生

设计模式之单例模式面试总结

2017-11-28 12:18 344 查看
单例模式

class SingleInstance {

private volatile static SingleInstance instance;

private SingleInstance() {

}

public static SingleInstance getInstance() {
if (instance == null) {                                          (i)
synchronized (SingleInstance.class) {
if (instance == null) {
instance = new SingleInstance();                     (j)
}
}
}
return instance;                                                 (k)
}


}

1、不加任何同步锁的时候,当有两个线程同时执行到(j)处时,会创建两个instance实例对象。

2、双重检查也不是绝对安全的,因为JVM编译器可能对执行进行重排,new一个对象时不是原子操作。

一个对象的初始化正常顺序:

(1)memory=allocate();//分配对象的内存空间

(2)ctorinstance(memory)//初始化对象

(3)设置栈上的引用指向刚分配的内存地址。

但是重排后可能会出现:

(1)memory=allocate();//分配对象的内存空间

(3)设置栈上的引用指向刚分配的内存地址。

(2)ctorinstance(memory)//初始化对象。

  如果线程A执行到(i)处,线程B执行到(j)处,并且线程B执行了重排列后的指令(1)(3),这时A线程抢到CPU资源,判空时,发现instance不为空,就直接返回(K)处的instance对象,由于这个对象是未初始化过的对象,那么在用该对象调用实例方法时,就会出现程序异常。

3、双重检查加锁“的方式可以既实现线程安全(不保证绝对安全),又能够使性能不受到很大的影响。

  双重检测机制在获取对象实例的时候,先判空,如果对象实例为空时才同步,不为空时直接返 回对象,并不是像单层的那样每次获取都要同步,这样减少了每次进入都要同步的时间。

4、加了双重检测机制还可能不安全,那么可以在声明对象的前面加一个volatitle关键字

    这个关键字可以可以防止指令重排,也可以保证线程访问的变量值是主内存中的最新值。那么在双重检测的基础上,就能够保证线程的安全。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐