请列举出至少4种单例可能被破坏的场景。

1反射对单例模式的破坏
采用反射的方式另辟蹊径实例了该类,导致程序中会存在不止一个实例。
解决方案
其思想就是采用一个全局变量,来标记是否已经实例化过了,如果已经实例化过了,第 二次实例化的时候,抛出异常

2clone()对单例模式的破坏
当需要实现单例的类允许clone()时,如果处理不当,也会导致程序中出现不止一个实例
解决方案
重写clone()方法,调clone()时直接返回已经实例的对象

3序列化对单例模式的破坏
在使用序列化/反序列化时,也会出现产生新实例对象的情况
解决方案
在反序列化时的回调方法 readResolve()中返回单例对象

4指令重排导致懒汉式单例模式失效
看似简单的一段赋值语句:instance = new Singleton();,其实JVM内部已经转换为多条指令:
memory = allocate(); //1:分配对象的内存空间
ctorInstance(memory); //2:初始化对象
instance = memory; //3:设置instance指向刚分配的内存地址
但是经过重排序后如下:
memory = allocate(); //1:分配对象的内存空间
instance = memory; //3:设置instance指向刚分配的内存地址,此时对象还没被初始化
ctorInstance(memory); //2:初始化对象
可以看到指令重排之后,instance指向分配好的内存放在了前面,而这段内存的初始化被排在了后面,在线程A初始化完成这段内存之前,线程B虽然进不去同步代码块,但是在同步代码块之前的判断就会发现instance不为空,此时线程B获得instance对象进行使用就可能发生错误
解决方案
private static volatile Singleton instance = null;

 

仅作为个人学习总结使用 如有侵权请联系删除

版权声明:玥玥 发表于 2021-03-20 3:03:13。
转载请注明:请列举出至少4种单例可能被破坏的场景。 | 女黑客导航