关于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种设计模式中,单例模式是比较简单的一种.然而,有时候越是简单的东西越容 ...
随机推荐
- poj1006 孙子定理
Biorhythms Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 127944 Accepted: 40566 Des ...
- jquery 图片滚动
效果图: $(function(){ $("#roll-img2").html($("#roll-img").html()); function r ...
- destoon实现商铺管理主页设置增加新菜单的方法
1.打开/lang/zh-cn/home.inc.php,找到9,10行替换如下: $HMENU = $DMENU = array('公司介绍', '供应产品', '采购清单', '新闻中心', '荣 ...
- [FML]学习笔记一Cross-validation交叉验证
在实际的工程中,有时labeled data的数量不足以留出validation sample(验证样本)否则会导致training sample(训练样本)的数量太少.为了解决这个问题,我们引入一种 ...
- AngularJS 基础教程二:
5.过滤器 过滤器的主要功能是格式化数据 可以使用Angular提供的过滤器,也可以自定义过滤器 Angular过滤器: currency(货币).date(日期).filter(子串匹配).json ...
- HOG detectMultiScale 参数分析
前段时间学习了HOG描述子及其与SVM结合在行人检测方面的应用. 当我们用训练好的模型去检测测试图像时,我们会用到detectMultiScale() 这个函数来对图像进行多尺度检测. 这是openc ...
- 剖析C语言中a=a+++++a的无聊问题
同僚们闲聊,突然就聊到了a+++++a的问题.这种纯属C语言 “二” 级的问题应该是从a+++a引申出来的吧.于是乎兄弟姐妹们开始讨论它的运算结果,以及改如何理解.更有人写出(a++)+(++a) a ...
- NOD32强制卸载工具使用方法【转】
装了ESET NOD32又忘记密码了,无法卸载,怎么办? 以下转自官网:http://faq.eset.com.cn/index.php?pid=254 [适用产品:ESET NOD32 防病毒软件4 ...
- Qt下HBoxLayout里的按钮有重叠
没想到是一个bug,而且六年了都没有解决: https://bugreports.qt.io/browse/QTBUG-14591 http://stackoverflow.com/questions ...
- 【转】android 兼容性测试 CTS 测试过程(实践测试验证通过)
原文网址:http://blog.csdn.net/jianguo_liao19840726/article/details/7222814 写这个博客的时候是为了记忆,建议大家还是看官方的说明,官方 ...