单例模式的实现
上面代码是一个经典的单例的双重监测的代码,这段代码在单线程环境下并没有什么问题,
但如果在是多线程环境下就可能出现线程安全问题。
多线程不安全的原因
上面代码不安全的原因如下:
当某一个线程执行到第一次监测,读取到的instance不为null时,
instance 的引用对象可能没有完全初始化。
因为 instance =new Singleton(); 可以分为以下三个步骤:
memory=allocate();//1.分配对象内存空间instance(memory);//2.初始化对象instance=memory;//3.设置instance指向刚分配的内存地址,此时instance!=null
上面的 2 和 3有可能被重排序:如下
memory=allocate();//1.分配对象内存空间instance=memory;//3.设置instance指向刚分配的内存地址,此时instance!=null,//但是对象还没有初始化完成!instance(memory);//2.初始化对象
多线程执行结果如下:
由于步骤2和步骤3 不存在数据依赖 关系,而且无论重排序前还是重排序后的执行结果在单线程环境下
是没有改变的,因此这种优化是允许的。但是指令重排只会保证串行语义的执行的一致性(单线程),但并
不关心多线程间的语义一致性。
所以当一条线程访问instance 不为null时,由于 instance 实例未必已初始化完成,也就造成了线程安全
问题。
怎样解决多线程下存在的问题
我们使用 volatile 禁止 instance变量被执行指令重排优化即可:
本文来自投稿,不代表本人立场,如若转载,请注明出处:http://www.souzhinan.com/kj/304369.html
赞 (149)
打赏 微信扫一扫
继微信之后,支付宝也上线重磅功能,涵盖六类服务
« 上一篇2020-01-29 06:54:14
共同战“疫”三大运营商启动多项应急举措
下一篇 »2020-01-29 07:24:15