关于双重检查成例的问题

zhakeer 2006-04-11 12:38:43
已经知道,对于java单例模式,如下的代码
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
是不成立或者说是不安全的,但是为什么
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
Singleton tmp=new Singleton();
instance=tmp;
}
}
}
return instance;
也不行呢?
...全文
284 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhakeer 2006-04-14
  • 打赏
  • 举报
回复
首先感谢各位的答复,但是你们的回答并不能解决我的疑惑,还请达人们给出正确的答案
gogon 2006-04-13
  • 打赏
  • 举报
回复
DCL 在1.4或者以前的版本里是不成立的.因为那时jvm的实现里,对于代码 MyClass mine=new MyClass()执行时,在完成new MyClass()的初始化前,就先将mine 赋予了指向即将创造的那个对象的地址.这样就可能导致调用尚未初始化的对象而导致的不可预期错误.
不过如果你使用的5.0的话,就不用担心了.这个错误已经被纠正了
水晶平衡木 2006-04-12
  • 打赏
  • 举报
回复
嗯,我认为后者没有什么不行的(除非instance=tmp;操作不是原子的,中间还可能生出什么异端来,^_^),支持一下。
zhakeer 2006-04-11
  • 打赏
  • 举报
回复
to classjava(原始野人) ( ) 信誉:105
如果仅仅是你说的3个前提
Singleton tmp=new Singleton();
instance=tmp;
就已经可以避免这种情况,但为什么还是说双重检查成例是不成立的呢?
classjava 2006-04-11
  • 打赏
  • 举报
回复

前提1:Java 使得它的每个线程使用独立的处理器和一个私有的内存空间,每一个线程的私有内存都会与主存交互与同步。synchronized 块会建立一个内存壁垒(memory barrier) ,当进入synchronized块时会建立一个read barrier :它会使得Thread的本地内存无效,并且从主存中读取所有的变量的值。当退出一个synchronized块时,它会确保将对所有本地内存的改变都同步到主存中。并且synchronized也会保证这段代码是原子操作。
前提2:假设一个new操作需要以下两个步骤(也许更多)1.分配相应内存2.调用构造函数。
前提3:我们不能在书写我们的代码时预计指令真正的执行顺序,他可能由于编译器,处理器和缓存机制的干预而变化。规范规定:编译器编译器,处理器和缓存机制可以任意改变指令顺序,只要不影响结果的值。
实例
public Resource getResource(){
if (resource == null){ // a:
synchronized(this){
if (resource==null){
resource = new Resource(); //b:
}
}
}return resource;//c
}

解释
有了以上的前提,我们可以讨论DCL是如何导致线程不安全的。假设:一个线程t1进入getResource()方法,并且执行到b处。这时另一个线程t2进入。当它在a处时t1刚好进行完分配内存的工作,而没有调用构造函数。这时T2会认为resource不为null因而直接来到c处,得到了一个错误的resource实例。显而易见会导致错误。
classjava 2006-04-11
  • 打赏
  • 举报
回复
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
zhakeer 2006-04-11
  • 打赏
  • 举报
回复
to icy_csdn() ( ) 信誉:110

你说的问题我是知道的,我问的是为什么
synchronized(Singleton.class){
if(instance==null){
Singleton tmp=new Singleton();
instance=tmp;
}
}
也不行
icy_csdn 2006-04-11
  • 打赏
  • 举报
回复
// Singleton instance
private static Singleton instance = null;

public static Singleton getInstance(){
/*
* 双重检验模式,内嵌同步机制。这里是第一重检验。
*/
if (instance == null) {
/*
* 同一时刻只有一个线程进入。
*/
synchronized (SSOTokenManager.class) {
/*
* 如果第二个线程在这里等待,它将发现instance已经被初始化,
* 因此不再会重新初始化instance变量,这就是双重检验。
*/

if (instance == null) {
/*
* 这里是关键,lazy实例化singleton变量。
*/
instance = new Singleton();
}
}
}
return (instance);
}
icy_csdn 2006-04-11
  • 打赏
  • 举报
回复
// Singleton instance
private static Singleton instance = null;

public static Singleton getInstance(){
/*
* 双重检验模式,内嵌同步机制。这里是第一重检验。
*/
if (instance == null) {
/*
* 同一时刻只有一个线程进入。
*/
synchronized (Singleton.class) {
/*
* 如果第二个线程在这里等待,它将发现instance已经被初始化,
* 因此不再会重新初始化instance变量,这就是双重检验。
*/

if (instance == null) {
/*
* 这里是关键,lazy实例化singleton变量。
*/
instance = new Singleton();
}
}
}
return (instance);
}
目 录 第1 章 模式的简史和形而上学........3 1.1 模式是什么...................................3 1.2 软件模式的简史...........................3 1.3 模式的起源...................................4 1.4 与道家思想的关系.......................5 1.5 软件的永恒之道...........................9 1.6 模式的要素...................................10 1.7 本书讲解模式的格式...................12 第2 章 统一建模语言UML 简介.....15 2.1 建造世界贸易中心.......................15 2.2 什么是UML.................................16 2.3 UML 包括什么.............................17 2.5 类图. 19 2.6 时序图...........................................27 2.7 状态图...........................................28 2.8 UML 及建模的工具.....................30 第3 章 软件的可维护性与可复用性35 3.1 软件系统的可维护性...................35 3.2 系统的可复用性...........................39 3.3 老子论“不武”...........................42 第4 章 “开-闭”原则(OCP).........45 4.1 什么是“开-闭”原则.................45 4.2 怎样做到“开-闭”原则.............45 4.3 与其他设计原则的关系...............47 4.4 策略模式对“开–闭”原则的支持 ........49 4.5 在其他设计模式中的体现...........50 4.6 一个重构做法的讨论...................54 第5 章 专题:Java 语言的接口........59 5.1 什么是接口...................................59 5.2 为什么使用接口...........................60 5.3 Java 接口常见的用法...................63 第6 章 专题:抽象类........................69 6.1 什么是抽象类...............................69 6.2 抽象类是用来继承.......................70 6.3 基于抽象类的模式和原则...........72 6.4 什么时候才应当使用继承复用...73 第7 章 里氏代换原则(LSP) .........79 7.1 美猴王的智慧...............................79 7.2 什么是里氏代换原则...................80 7.3 里氏代换原则在设计模式中的体现 ....... 82 7.4 墨子论“取譬”...........................83 7.5 从代码重构的角度理解...............84 第8 章 依赖倒转原则(DIP)..........95 8.1 为何而“倒转”...........................95 8.2 复用与可维护性的“倒转”.......96 8.3 依赖倒转原则...............................96 8.4 怎样做到依赖倒转原则...............99 8.5 Java 对抽象类型的支持...............101 8.6 一个例子:账号、账号的种类和账号 的状态...... 103 8.7 墨子论“取周”...........................106 8.8 依赖倒转原则的长处和短处.......107 第9 章 接口隔离原则(ISP) ..........109 9.1 什么是接口隔离原则...................109 9.2 一个角色隔离原则的例子...........110 9.3 定制服务的例子...........................112 第10 章 合成/聚合复用原则(CARP) ....... 115 10.1 合成和聚合的区别.....................115 10.2 复用的基本种类.........................115 10.3 从代码重构的角度理解.............117 第11 章 迪米特法则(LoD)...........121 11.1 迪米特法则的各种表述.............121 11.2 狭义的迪米特法则.....................121 《Java 与模式》作者阎宏博士 电子工业出版社出版 11.3 迪米特法则与设计模式.............126 11.4 广义的迪米特法则.....................128 11.5 广义迪米特法则在类的设计上的体 现....129 11.6 广义迪米特法则在代码层次上的实 现....133 11.7 老子论“圣人之治”.................133 第12 章 简单工厂(Simple Factory)模式 ........139 12.1 工厂模式的几种形态.................139 12.2 简单工厂模式的引进.................139 12.3 简单工厂模式的结构.................146 12.4 简单工厂模式的实现.................148 12.5 简单工厂模式与其他模式的关系 ........153 12.6 模式的优点和缺点.....................155 12.7 简单工厂模式在Java 中的应用156 12.8 女娲抟土造人.............................160 第13 章 工厂方法(Factory Method)模式 ........165 13.1 引言.............................................165 13.2 工厂方法模式的结构.................167 13.3 工厂方法模式在农场系统中的实现 ........172 13.4 关于工厂方法模式的实现.........177 13.5 Java 语言中工厂方法模式的例子 ........179 13.6 工厂方法模式与其他模式的关系 ........182 13.7 女娲举绳造人.............................185 13.8 其他的例子.................................185 第14 章 抽象工厂(Abstract Factory)模 式....193 14.1 引言.............................................193 14.2 问题.............................................195 14.3 抽象工厂模式的结构.................198 14.4 在什么情形下应当使用抽象工厂模 式....204 14.5 抽象工厂模式在农场系统中的实现 ....... 205 14.6 抽象工厂模式的另一个例子.....211 14.7 “开-闭”原则..............................212 14.8 关于模式的实现.........................213 14.9 女娲造万物的故事.....................214 第15 章 单例(Singleton)模式.......221 15.1 引言.............................................221 15.2 单例模式的结构.........................222 15.3 在什么情况下使用单例模式.....228 15.4 单例类的状态.............................229 15.5 一个实用的例子:属性管理器.230 15.6 Java 语言中的单例模式.............235 15.7 专题:不完全的单例类.............239 15.8 相关模式.....................................240 15.9 附录:双重检查成例的研究.....243 15.10 给读者的一点建议...................247 第16 章 专题:单例模式与MX 记录 ....... 249 16.1 问题与解决方案.........................249 16.2 目录服务与MX 记录................251 16.3 JNDI 架构介绍...........................252 16.4 如何使用JNDI 编程..................253 16.5 系统设计.....................................255 16.6 讨论.............................................261 第17 章 专题:多例(Multiton)模式与多 语言支持.. 267 17.1 引言.............................................267 17.2 多例模式.....................................269 17.3 多语言项目的设计.....................272 第18 章 专题:序列键生成器与单例及多 例模式...... 283 18.1 问题.............................................283 18.2 将单例模式应用到系统设计中.285 18.3 将多例模式应用到系统设计中.297 18.4 讨论.............................................300 第19 章 建造(Builder)模式..........301 19.1 引言.............................................301

51,397

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧