关于DCLP实现的单例模式的一些想法
关于DCLP实现的单例模式的一些想法
我之前写过单例的文章( http://www.cnblogs.com/mkdym/p/4908644.html ),但是现在又有了一些想法,不想再在原来那篇文章上更新,所以独开一篇。
看到一些书或者文章讲单例模式的时候,总要说起DCLP,并且得出的结论是DCLP是不可靠的,也就不能用它来实现单例。即下面这样做是错误的:
class SingletonAA
{
public:
static SingletonAA& get_instance_ref()
{
if (NULL == p_) // 1st check
{
scoped_lock lock;
if (NULL == p_) // 2nd check
{
p_ = new SingletonAA();
}
}
return *p_;
} private:
SingletonAA()
{
//...
} ~SingletonAA()
{
//...
} private:
static SingletonAA *p_; }; SingletonAA *SingletonAA::p_ = NULL;
因为new那一句不是原子的,分了3步,而且顺序不一定,这个顺序又会影响第一次检查的结果。接着他们又讨论了volatile关键字和乱序优化,然后得出结论这个关键字也不能使DCLP变得正确,或者说不能轻松的使DCLP变得正确。
但是他们讲这个问题的时候全部的前提是用单例对象的指针本身去做了判断条件,这就是诱因:单例对象的创建和单例的判断是对同一个元素读写,而“写”太“复杂”了!
那么我不用单例对象去做判断不就行了吗?如下:
class SingletonAA
{
public:
static SingletonAA& get_instance_ref()
{
if (!init_flag_) // 1st check
{
scoped_lock lock;
if (!init_flag_) // 2nd check
{
p_ = new SingletonAA();
init_flag_ = true;
}
}
return *p_;
} private:
//... private:
static SingletonAA *p_;
static bool volatile init_flag_;
}; SingletonAA *SingletonAA::p_ = NULL;
bool volatile SingletonAA::init_flag_ = false;
我换用一个bool标志,bool变量在vc上是一个字节的,操作只需一条指令,是原子的。而且声明成volatile,确保编译器不对它做优化。
按我的不准确的知识,编译器或CPU可能会对
p_ = new SingletonAA();
和
init_flag_ = true;
这两句调整顺序,因为他们两句没有关联,这就又会出错。那么我制造一个关联:
init_flag_ = p_ ? true : false;
使init_flag_的赋值依赖于对象的创建,按我的理解,此时编译器和CPU都应该使设置标志语句后于对象创建语句,那么就没有错误了。
假如编译器认为p_在执行完new后一定不为0,那么它就又可以优化init_flag_的赋值了。那么这种情况会不会出现,编译器是否会这样认为?
Need Help
Need Help
Need Help
(重说三)
因为我想得到大家的关注,所以可耻的勾选了“发布至博客园首页”,如果最后没有在首页出现,我就把这句话删掉,免的丢我的小脸。
关于DCLP实现的单例模式的一些想法的更多相关文章
- Java设计模式4:单例模式
前言 非常重要,单例模式是各个Java项目中必不可少的一种设计模式.本文的关注点将重点放在单例模式的写法以及每种写法的线程安全性上.所谓"线程安全性"的意思就是保证在创建单例对象的 ...
- 【Java】Java 深入探讨 单例模式的实现
在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就单例设计模式详细的探讨一下. 所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在 ...
- 深入Java单例模式【转载】
在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就单例设计模式详细的探讨一下. 所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在 ...
- 单例模式(Winform窗体的实现)
在我的设计模式分类当中,我选择单例模式作为我第一个要写的设计模式,其一,单例模式简单.容易理解让人接受,其二,单例模式很常用,在实际的Winform窗体应用开发中能够带来更好的客户体验. 单例模式的核 ...
- java中的单例模式与doublecheck
转自: http://devbean.blog.51cto.com/448512/203501 在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就单 ...
- 【转载】深入Java单例模式
原文出处:http://devbean.blog.51cto.com/448512/203501 在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就 ...
- java模式:深入单例模式
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://devbean.blog.51cto.com/448512/203501 在GoF ...
- 深入Java单例模式
在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容易出现问题.下面就单例设计模式详细的探讨一下. 所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在. ...
- 深入Java单例模式(转)
深入Java单例模式 源自 http://devbean.blog.51cto.com/448512/203501 在GoF的23种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容 ...
随机推荐
- (四)CodeMirror - API
内容相关 cm.getValue() cm.setValue() cm.getRange() editor.getRange({line:1},{line:2}) // 获取内容块字符 cm.repl ...
- MDX示例:求解中位数、四分位数(median、quartile)
一个人力资源咨询集团通过网络爬虫采集手段将多个知名招聘网站上发布的求职和招聘等信息准实时采集到自己的库里,形成一个数据量浩大的招聘信息库,跟踪全国招聘和求职的行业.工种.职位.待遇等信息,并通过商业智 ...
- 【Nutch2.2.1基础教程之1】nutch相关异常
1.在任务一开始运行,注入Url时即出现以下错误. InjectorJob: Injecting urlDir: urls InjectorJob: Using class org.apache.go ...
- setInterval()、clearInterval()、setTimeout()和clearTimeout()js计数器方法
原文地址:http://caibaojian.com/setinterval-settimeout.html window.setInterval()方法 介绍 周期性地调用一个函数(function ...
- JS window对象的top、parent、opener含义
.top 该变更永远指分割窗口最高层次的浏览器窗口.如果计划从分割窗口的最高层次开始执行命令,就可以用top变量. .opener opener用于在window.open的页面引用执行该window ...
- WORD-如何解除WORD文档的锁定
Word文档保护破解 般来说WORD文档有两种密码打开密码和文档保护密码下面介绍几种破解文档保护密码方法 方法1:插入文件法 启动WORD新建空白文档执行插入→文件打开插入文件对框定位需要解除保护文档 ...
- VLSI和ASIC的区别(转)
VLSI和ASIC是不同的两个概念 VLSI(Very Large Scale Integrate circuit)是指集成电路的规模,有时也指制造集成电路所使用的工艺,VLSI工艺一般都在1um以下 ...
- 原已经安装好的nginx,现在需要添加一个未被编译安装的模块--echo-nginx-module-0.56
为了测试一个NGINX变量,将NGINX加了一个编译模板echo-nginx-module-0.56. 参照如下文件 1,先看以前NGINX有哪些东东. sbin/nginx -Vnginx vers ...
- GBT28181中的RTP
国标中说h264数据按照RFC3984打包,但是国标的测试工具——SPVMN,却不支持RFC3984的打包方式.无奈之下直接用RFC3550的方式打包,其实就是分包,然后加上RTP头,对于一帧的结束, ...
- Php官方指导安装与配置
From:http://php.net/manual/zh/install.php 提示:如需在 Windows 平台设置并立即运行 PHP,您还可以:下载 WebMatrix 安装与配置 安装前需要 ...