DCL的失效:现实与初衷的背离
最近看了 Brian Goetz 写的一篇有关 DCL 的文章:Double-checked locking: Clever, but broken。(2001 年发表于 JavaWorld 上)
这篇文章讲述了 DCL 设计的初衷,但是因为 JVM 的不同实现(没有严格遵循 JMM 规范)导致 DCL 在实际应用中失效。
1. DCL 的设计初衷
DCL 是为了支持 Lazy initialization 而设计的。
我们有多种方式去实现单例模式:
- Eager initialization: 饿加载,当类加载器加载类时就初始化类变量。这种方式可以保证初始化的原子性,但降低了程序的启动性能(类加载过程中的初始化阶段对类变量初始化)。
- Lazy initialization: 懒加载,当需要使用类变量时才进行初始化。这种方式可以提高程序的启动性能,但需要同步来保证初始化的原子性,无疑带来了同步开销。
DCL 的目标是(1)提高程序的启动性能,(2)降低同步开销。
代码示例:
class SomeClass {
private Resource resource = null;
public Resource getResource() {
if (resource == null)
resource = new Resource();
return resource;
}
}
2. DCL 失效的原因
DCL 要真正有效,需要依赖 JVM 真正遵循了 JMM 规范。
实际中,编译器、处理器、缓存都可以“自由”执行代码(乱序执行),只要保证 as-if-serial semantics 就行。
这里要提及 synchronized 的作用:
- 互斥执行某段代码
- 触发 memory barrier ,强制线程的工作内存与住内存同步
适当地使用同步可以保证:一个线程预期地看到另一个线程的影响(The proper synchronization guarantees that one thread will see the effects of another in a predictable manner)。
DCL 之所以失效,是因为没有同步地使用 resource。(与上文提到的乱序执行有关,这个与具体的 JVM 版本有关,很多 JVM 实现没有严格实现JMM规范)
3. 解决方案
(1)不使用 DCL;
(2)使用饿加载(Eager initialization),由类加载器保证类变量初始化的互斥性(每个类只会加载一次);
(3)懒加载有个特例:只含有一个类变量,不含类方法、实例变量、实例方法;
(4)对 32bit primitive values 有效。
DCL的失效:现实与初衷的背离的更多相关文章
- Design Patterns in Android
对日常在 Android 中实用设计模式进行一下梳理和总结,文中参考了一些网站和大佬的博客,如 MichaelX(xiong_it) .菜鸟教程.四月葡萄.IAM四十二等,在这里注明下~另外强烈推荐图 ...
- Android经典的设计模式
[单例模式][Build模式][原型模式][工厂模式][策略模式][状态模式][责任链模式][解释器模式][命令模式][观察者模式][备忘录模式][迭代器模式] [模板方法模式][访问者模式][中介者 ...
- Android中的创建型模式总结
共5种,单例模式.工厂方法模式.抽象工厂模式.建造者模式.原型模式 单例模式 定义:确保某一个类的实例只有一个,而且向其他类提供这个实例. 单例模式的使用场景:某个类的创建需要消耗大量资源,new一个 ...
- python的高级应用
记录一下Python函数式编程,高级的几个BIF,高级官方库方面的用法和心得. 函数式编程 函数式编程是使用一系列函数去解决问题,按照一般编程思维,面对问题时我们的思考方式是"怎么干&quo ...
- SQL SERVER 中is null 和 is not null 将会导致索引失效吗?
其实本来这个问题没有什么好说的,今天优化的时候遇到一个SQL语句,因为比较有意思,所以我截取.简化了SQL语句,演示给大家看,如下所示 declare @bamboo_Code varchar(3); ...
- ddl dml dcl
DCL数据控制语言 创建临时表空间 create temporary tablespace user_temp tempfile 'E:/oracle/product/10.1.0/oradata/o ...
- 用happen-before规则重新审视DCL(转)
编写Java多线程程序一直以来都是一件十分困难的事,多线程程序的bug很难测试,DCL(Double Check Lock)就是一个典型,因此对多线程安全的理论分析就显得十分重要,当然这决不是说对多线 ...
- DCL,DDL,DML,DQL
DCL(Data Control Language)是数据库控制语言. 是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句. 在默认状态下,只有sysadmi ...
- DML,DDL,DCL,DQL的区别
DML 英文缩写 DML = Data Manipulation Language,数据操纵语言,命令使用户能够查询数据库以及操作已有数据库中的数据的计算机语言.具体是指是UPDATE更新.INS ...
随机推荐
- java.util.HashMap和java.util.HashTable (JDK1.8)
一.java.util.HashMap 1.1 java.util.HashMap 综述 java.util.HashMap继承结构如下图 HashMap是非线程安全的,key和value都支持nul ...
- 一个三维点类Gpoint3的实现
1 类设计 基本功能 (1)默认构造时,自动初始化为(0,0,0): (2)支持点之间的加.减运算: (3)支持点与常量数据的加.减.乘除运算: (4)支持点之间的相等或不能判断 (5)如果把点类看作 ...
- python源文件转换成exe问题解决贴
项目上做一个小工具,通过webservice接口实现配置下发.python文件调试通过了,想把它抓换成exe,网上查了下,得知有py2exe这个好用精简的小工具,本以为分分钟搞定的事情,结果经历了九转 ...
- 学习python登录demo
要求编写登录接口 : 1. 输入用户名和密码 2.认证成功后显示欢迎信息 3.用户名输错,提示用户不存在,重新输入(5次错误,提示尝试次数过多,退出程序) 4.用户名正确,密码错误,提示密码错误,重新 ...
- 轻谈BFC
BFC 定义 CSS2.1的定义 Block formatting contexts 9.4.1 Block formatting contexts Floats, absolutely positi ...
- OC对象与Core Foundation对象的转换
OC对象使用了ARC,自己主动释放内存,可是CF中的对象没有ARC,必需要手动进行引用计数和内存释放. 两者对象之间的互相转换有三种形式: 1.__bridge: 直接转换,部改变对象的持有状况: i ...
- OpenTK教程-0序言
记得很久之前,我写过一个基于.NET的3D开发框架/工具比较.当时选定的技术是WPF.但是随着项目发展,需要处理的图形数量越来越多,基于WPF的处理起来性能有问题,最后还是使用了基于OpenTK的解决 ...
- MD5加密--Java
MD5 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321(R.R ...
- Docker-py 的使用
Docker SDK for Python A Python library for the Docker Engine API 具体文档这里,https://docker-py.readthedoc ...
- python __getattr__ 巧妙应用
在之前的文章有提到__getattr__函数的作用: 如果属性查找(attribute lookup)在实例以及对应的类中(通过__dict__)失败, 那么会调用到类的__getattr__函数, ...