延迟初始化,双重检查加锁的陷阱
来源:互联网 发布:c语言随机数生成 编辑:程序博客网 时间:2024/05/21 06:26
在初始化类时,有时为了避免不必要的开销,我们会采用延迟初始化的方式来构造类。在多线程的环境中,我们经常会使用双重检查加锁的方式来初始化类,甚至在百度移动应用统计的源码中,我就看到了许多使用这种延迟初始化的方式,如 程序1-1
public class DoubleCheckedLocking { private static Resource resource; public static Resource getInstance() { if(resource == null) { synchronized(DoubleCheckedLocking.class) { if(resource == null) { resource = new Resource(); } } } return resource; }}
程序 1-1这样的代码是存在问题的,对象在没有同步的状态下缺少了Happens-Before的关系,可能出现重排序的问题。
初始化一个新的对象时需要写入多个变量,即新对象中的各个域,同样,在发布一个引用时也需要写入一个变量,即新对象的引用。如果新对象引用的写入操作与对象中各个域的写入操作重排序,如程序1-1,当A线程调用该方法后,这时候resource可能非空,因此B线程在在调用没有同步的判断代码时将直接返回resource,但是这时可能看到Resource实例还未构造完成,因此可能看到某些或全部状态中包含的是无效值(尽管在构造函数中设置的域值似乎是第一次向这些域中写入的值,因此不会有“更旧的”值被视为失效值,但Object的构造函数会在子类构造函数运行之前先将默认值写入所有的域,因此,某个域的默认值可能被视为失效值)。从而调用了一个部分构造的对象,引发错误。
0 0
- 延迟初始化,双重检查加锁的陷阱
- Java并发编程实战--双重检查加锁( double check lock)与延迟初始化占位
- 并发编程的艺术-双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- 双重检查锁定与延迟初始化
- LintCode 把排序数组转换为高度最小的二叉搜索树
- Linux操作系统使用及linux常用命令
- dom4j
- 对JVM的理解
- HDU1257 最少拦截系统 —— LIS
- 延迟初始化,双重检查加锁的陷阱
- 平衡二叉查找树插入节点操作( AVLTree ):旋转、调整平衡
- MySQL
- poj
- 常用的机器学习算法大汇总
- Java I/O
- iOS Cocoapods 第一次使用
- 动态代理解决表单提交的中文乱码问题
- 异常:java.lang.IllegalArgumentException