- 浏览: 24543 次
- 来自: 上海
文章分类
最新评论
双重检查锁定失效问题,一直是JMM无法避免的缺陷之一.了解DCL失效问题, 可以帮助我们深入JMM运行原理.
要展示DCL失效问题, 首先要理解一个重要概念- 延迟加载(lazy loading).
要展示DCL失效问题, 首先要理解一个重要概念- 延迟加载(lazy loading).
非单例的单线程延迟加载示例:
private Resource res = null;
public Resource getResource() {
//普通的延迟加载
if (res == null)
res = new Resource();
return res;
}
}
非单例的多线程延迟加载示例:
Class Foo {
private Resource res = null;
public synchronized Resource getResource() {
//获取实例操作使用同步方式, 性能不高
if (res == null)
res = new Resource();
return res;
}
}
非单例的DCL多线程延迟加载示例:
Class Foo {
private Resource res = null;
public Resource getResource() {
if (res == null) {
//只有在第一次初始化时,才使用同步方式.
synchronized(this) {
if(res == null) {
res = new Resource();
}
}
} // end if null
return res;
}
}
Double-Checked Locking看起来是非常完美的。但是很遗憾,根据Java的语言规范,上面的代码是不可靠的。
出现上述问题, 最重要的2个原因如下:
1, 编译器优化了程序指令, 以加快cpu处理速度.
2, 多核cpu动态调整指令顺序, 以加快并行运算能力.
问题出现的顺序:
return res;
}
}
非单例的DCL多线程延迟加载示例:
Class Foo {
private Resource res = null;
public Resource getResource() {
if (res == null) {
//只有在第一次初始化时,才使用同步方式.
synchronized(this) {
if(res == null) {
res = new Resource();
}
}
} // end if null
return res;
}
}
Double-Checked Locking看起来是非常完美的。但是很遗憾,根据Java的语言规范,上面的代码是不可靠的。
出现上述问题, 最重要的2个原因如下:
1, 编译器优化了程序指令, 以加快cpu处理速度.
2, 多核cpu动态调整指令顺序, 以加快并行运算能力.
问题出现的顺序:
1, 线程A, 发现对象未实例化, 准备开始实例化
2, 由于编译器优化了程序指令, 允许对象在构造函数未调用完前, 将共享变量的引用指向部分构造的对象, 虽然对象未完全实例化, 但已经不为null了.
3, 线程B, 发现部分构造的对象已不是null, 则直接返回了该对象.
不过, 一些著名的开源框架, 包括jive,lenya等也都在使用DCL模式, 且未见一些极端异常.
说明, DCL失效问题的出现率还是比较低的.
接下来就是性能与稳定之间的选择了?
DCL的替代Initialize-On-Demand:
public class Foo {
// 私有静态内部类, 只有当有引用时, 该类才会被装载
private static class LazyFoo {
public static Foo foo = new Foo();
}
public static Foo getInstance() {
return LazyFoo.foo;
}
}
维基百科的DCL解释:
http://en.wikipedia.org/wiki/Double-checked_locking
DCL的完美解决方案:
http://www.theserverside.com/patterns/thread.tss?thread_id=39606
2, 由于编译器优化了程序指令, 允许对象在构造函数未调用完前, 将共享变量的引用指向部分构造的对象, 虽然对象未完全实例化, 但已经不为null了.
3, 线程B, 发现部分构造的对象已不是null, 则直接返回了该对象.
不过, 一些著名的开源框架, 包括jive,lenya等也都在使用DCL模式, 且未见一些极端异常.
说明, DCL失效问题的出现率还是比较低的.
接下来就是性能与稳定之间的选择了?
DCL的替代Initialize-On-Demand:
public class Foo {
// 私有静态内部类, 只有当有引用时, 该类才会被装载
private static class LazyFoo {
public static Foo foo = new Foo();
}
public static Foo getInstance() {
return LazyFoo.foo;
}
}
维基百科的DCL解释:
http://en.wikipedia.org/wiki/Double-checked_locking
DCL的完美解决方案:
http://www.theserverside.com/patterns/thread.tss?thread_id=39606
发表评论
-
多语言编程
2009-04-14 02:10 0计算机语言就像鲨鱼,要是保持静止就会死。和现实生活中的语言一样 ... -
SchemaSpy
2009-04-17 02:35 0SchemaSpy: Graphical Database S ... -
微软架构师分类参考
2009-04-24 07:22 1155企业架构师EA(Enterprise Architec ... -
Java Memory Model(JMM)
2009-07-27 01:41 946内存模型 (memory model)内 ... -
进程间通信方式
2009-09-16 06:33 1519Windows下的进程间通信方式: 文件映射、共享内存、管道( ... -
多语言编程
2009-04-14 02:10 611计算机语言就像鲨鱼,要是保持静止就会死。和现实生活中的语言一样 ... -
SchemaSpy
2009-04-17 02:35 322SchemaSpy: Graphical Database S ... -
微软架构师分类参考
2009-04-24 07:22 0企业架构师EA(Enterprise Architec ... -
Double-Checked Locking失效问题
2009-07-27 01:33 0双重检查锁定失效问题, ... -
Java Memory Model(JMM)
2009-07-27 01:41 0内存模型 (memory model)内 ... -
进程间通信方式
2009-09-16 06:33 0Windows下的进程间通信方式: 文件映射、共享内存、管道( ... -
多语言编程
2009-04-14 02:10 0计算机语言就像鲨鱼,要是保持静止就会死。和现实生活中的语言一样 ... -
SchemaSpy
2009-04-17 02:35 0SchemaSpy: Graphical Database S ... -
微软架构师分类参考
2009-04-24 07:22 0企业架构师EA(Enterprise Architec ... -
Double-Checked Locking失效问题
2009-07-27 01:33 0双重检查锁定失效问题, ... -
Java Memory Model(JMM)
2009-07-27 01:41 0内存模型 (memory model)内 ... -
进程间通信方式
2009-09-16 06:33 0Windows下的进程间通信方式: 文件映射、共享内存、管道( ... -
用户需求和产品需求
2009-09-02 10:34 1442需求获取和分析是软件开发至关重要的一环,对于一个大的软件项目来 ...
相关推荐
在介绍双检锁模式(Double-Checked Locking Pattern,DCLP)的C++实现中,Scott Meyers和Andrei Alexandrescu在其2004年的文章中指出,传统的单例模式实现并不具备线程安全性。单例模式是设计模式中经常被提及的一种...
Double-Checked Locking(DCL)是一种常用于延迟初始化的优化技术,其核心思想是在第一次检查实例是否为空之后,再使用`synchronized`关键字进行第二次检查。然而,DCL模式在JMM中可能会失效。 ##### DCL失效案例...
- 可以通过双重检查锁定(Double-Checked Locking)优化性能。 **线程安全问题及解决方案** - **问题**:在多线程环境中,若不采取措施,则可能会导致单例模式失效,即生成多个实例。 - **解决方案**: - 使用`...
Druid通过优化内部实现,如使用双重检查锁定(double-checked locking)避免并发问题,以及使用直接内存分配提升数据传输速度,实现了比DBCP和C3P0更高的性能。同时,Druid的连接池管理算法也更加智能,能有效避免...
#### DCL(Double-Checked Locking)失效 DCL是一种常见的懒加载模式,旨在减少不必要的同步开销。然而,在Java中,DCL模式可能存在缺陷,尤其是在早期的JVM版本中。 ##### DCL的基本原理 DCL模式通常采用以下...
懒汉式的一个改进是**双重检查锁定(Double-Checked Locking, DCL)**,它尝试减少不必要的同步开销: ```java public class Singleton { private volatile static Singleton instance = null; private Singleton...
为确保线程安全,通常使用双检锁/双重校验锁(DCL,即double-checked locking)或者静态内部类来实现。 5. **组件间的通信**:Activity和服务之间可以通过Intent进行通信,服务可以通过startActivityForResult()...
- **解决方案**: 使用互斥锁(Mutex)或者双重检查锁定(Double-Checked Locking)来控制并发访问。 - **缓存雪崩**: 缓存中大量数据同时失效,导致所有请求都落到后端数据库。 - **解决方案**: 分布式缓存失效策略,...
文章提到的双重检查锁定(Double-Checked Locking,简称DCL)是一个在单例模式中用来优化性能的编程技巧。该技巧的核心在于减少同步的开销,在多线程环境下,仅在实例未被创建时才同步。然而,这个技巧在Java早期...
为了解决这个问题,可以使用双重检查锁定(Double-Checked Locking,DCL)优化懒汉式,但这需要依赖于Java内存模型(JMM)来保证正确性,如下所示: ```java public class Singleton { private volatile static ...
2. **双重检查锁定**:在单例模式中,`volatile`结合双重检查锁定(Double-Checked Locking)可以保证线程安全地创建单例。首先检查实例是否已创建,如果未创建,才进行同步创建,`volatile`确保在多个线程中只实例...
单例模式通过双重检查锁定(double-checked locking)来实现,这既保证了线程安全,又避免了不必要的同步开销。 在`MySQLPool`类中,`MysqlDataSource` 是连接池的基础,它是JDBC的MySQL数据源实现,提供了配置...
例如,懒汉式单例模式中,可以在 `getInstance()` 方法上添加 `synchronized` 关键字,或者采用双重检查锁定(Double Checked Locking)模式。 2. **类加载器问题的解决**:为了解决不同类加载器加载同一个类产生的...