博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java基础教程:多线程杂谈——双重检查锁与Volatile
阅读量:5241 次
发布时间:2019-06-14

本文共 1610 字,大约阅读时间需要 5 分钟。

Java基础教程:多线程杂谈——双重检查锁与Volatile

 双重检查锁

  有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化。此时程序员可能会采用延迟初始化。但要正确实现线程安全的延迟初始化需要一些技巧,否则很容易出现问题。比如,下面是非线程安全的延迟初始化对象的示例代码:

public class A{            private Instance instance;            public Instance getInstance(){                if(instance==null){                        instance = new Instance();                    }                }                return instance;            } }

  因为在多线程执行下,instance可能被多次初始化。我们可以对 getInstance() 做同步处理来实现线程安全的延迟初始化。示例代码如下:

public class A{            private Instance instance;            public Instance getInstance(){                if(instance==null){                    synchronized(A.class){                        if(instance==null)                           instance = new Instance();                    }                }                return instance;            } }

  可见,我们用了两次is null 判断,如上则是通过双重检查锁定来降低同步的开销

问题

  前面的双重检查锁定示例代码(instance = new Singleton();)创建一个对象。这一行代码可以分解为如下的三行伪代码:

memory = allocate();   //1:分配对象的内存空间 ctorInstance(memory);  //2:初始化对象 instance = memory;     //3:设置 instance 指向刚分配的内存地址

  上面三行伪代码中的 2 和 3 之间,可能会被重排序(在一些 JIT 编译器上,这种重排序是真实发生的,详情见参考文献 1 的“Out-of-order writes”部分)。2 和 3 之间重排序之后的执行时序如下:

memory = allocate();   //1:分配对象的内存空间 instance = memory;     //3:设置 instance 指向刚分配的内存地址                        // 注意,此时对象还没有被初始化!ctorInstance(memory);  //2:初始化对象

  所以说可能出现一种情况就是,锁内线程创建对象时仅仅分配了内存地址还未完成初始化,锁外的线程就会判断is null 为false,从而返回一个半成品实例。问题的关键所在就是创建对象并非原子操作,从而被编译器进行指令重排序,导致发生意想不到为问题。

解决办法

  

  为了防止这个过程的重排序,我们需要将变量设置为volatile类型的变量,volatile的禁止重排序保证了操作的有序性

 

转载于:https://www.cnblogs.com/MrSaver/p/11350115.html

你可能感兴趣的文章
湖南集训day4
查看>>
在终端更改MAC的MySQL的root密码
查看>>
求整数的二进制表示中1的个数 (转)
查看>>
高仿BiliBili的iOS客户端源码项目
查看>>
poj 1228 凸包
查看>>
webapi返回json格式优化 转载https://www.cnblogs.com/GarsonZhang/p/5322747.html
查看>>
Hibernate关系映射(三) 多对一和一对多
查看>>
网络上找到的 SQL 存储过程学习
查看>>
ZipFile解压文件不改变压缩包内文件修改日期的方法
查看>>
妙味——任意值变化的运动框架
查看>>
31种选择器的应用
查看>>
fck用法总结 待续。。。
查看>>
拓展训练总结
查看>>
HDU 1007 Quoit Design竟然要分治
查看>>
简单的SQL语句
查看>>
linux grep 搜索查找
查看>>
指针实验报告
查看>>
for循环语句
查看>>
python-加密
查看>>
实用小命令汇总(个人使用)
查看>>