单例模式双重检查锁模式为什么必须加 volatile?
2023-03-15 23:26:08 时间
单例模式双重检查锁模式为什么必须加 volatile?
学习设计模式时候,知道单例模式是一种很常见的设计模型,其目的就是为了避免创建过多的对象,给jvm造成比较大的压力,之前也对单例模型进行了比较详细的描述,详情参考我之前博客:链接
如果要实现一种线程安全的单例模型,一般都会采用双重检查锁模式
public class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
这里,就会有疑问,为什么要双重检查?
答:这里分情况,如果不用第一个if判断,在多线程情况下,所有的线程都会进行抢锁,所以其实就是串行执行的;如果不用第二个if判断,因为经过第一个if判断,多个线程都会进来,不过只有一个线程能抢到锁,因为singleton对象是null,所以会进行new Singleton,这种情况,如果不加第二个if判断,第一个线程创建对象之后,之后线程会继续创建的,所以这种就没做到单例
双重检查的原因知道之后,为什么要加volatile关键字?在前面的学习,我们知道了volatile关键字有两个关键作用,volatile可以保证并发的可见性,同时也可以保证有序性。所以上面代码Singleton对象加上volatile关键字的作用主要是为了保证有序性。
在new Singleton时候,会进行如下的过程,①先给Singleton分配内存空间、②调用Singleton的构造函数进行初始化操作③将Singleton对象指向分配的内存空间
所以,不加volatile关键字,进行代码编译时候是会进行指令重排序的,如图,new Singleton的过程不一定是按照123这个顺序来的,可能是132顺序执行,这种情况,调用第3步,Singleton对象已经不为null,所以会被其它线程调用,不过还没进行第2步初始化操作,所以会报错
相关文章
- 需求变化与IoC
- IoC/DIP其实是一种管理思想
- 扩展PHP的五个简单技巧,让单服务器并行支撑30000用户
- Tier5 新标准?别闹了,亲
- Bob大叔忠告:专业软件开发者必须精通的事项
- IT 业的下一次革命:SDN 软件定义网络
- 解决Java/MySQL性能问题的思路
- 十款值得我们选择的开源开发板
- 路透社:美国政府成恶意程序最大买家
- Spring Cloud实战小贴士:Ribbon的饥饿加载(eager-load)模式
- PHP语言需要避免的10大误区
- 500家国内AI企业大数据分析:产业布局与融投风云
- PHP 语言需要避免的 10 大误区
- 用星际争霸讲解PHP面向对象的概念
- 一些编程上的策略
- 深度解析:清理烂代码
- 一些编程上的策略
- 跟Facebook学反欺诈 看CopyCatch算法如何搞定Lockstep
- 精益数据分析卡片:留存分析
- 先要好代码? 还是好产品?