复杂的Singleton
来源:互联网 发布:7u分享网络app 编辑:程序博客网 时间:2024/06/05 02:40
//不包含成员初始化的SingletonCObjFactory& CObjFactory::Instance(){ static CObjFactoryinstance; return instance;}//包含成员初始化的SingletonCEngineManager& CEngineManager::Instance(){ static CEngineManagers_kbEngineMgr; try { if(s_kbEngineMgr.m_bInited) { return s_kbEngineMgr; } else { s_kbEngineMgr.m_sec.Lock(); if(!s_kbEngineMgr.m_bInited) { s_kbEngineMgr.m_kbReasoningMgr.Release(); CInnerManager::Instance().Release(); s_kbEngineMgr.LoadBuffParam(); ...}
两种用法在单线程里都不会有什么问题
但是并发的时候 这两种方式都会存在严重的问题
首先明确一点 static 定义的变量只会初始化一次
先来看第一个例子
加入有两个线程都调用了CObjFactory& CObjFactory::Instance();
那么将会发生如下情况
第一个线程执行到了static CObjFactoryinstance;
调用了CObjFactory的构造函数 加入在构造函数执行到一般的时候发生了context swtich 构造函数并没有执行完毕
而第二线程在这时进入了CObjFactory& CObjFactory::Instance()
由于static的定义
static CObjFactoryinstance;这句语句并不会被二次执行
第二个线程直接返回return instance;
如果这时对返回的对象调用成员函数会有如下两种情况
1.没有访问成员变量的成员函数
这不会造成什么问题
2.有访问成员变量的成员函数
程序崩溃
原因很简单 由于第一个线程进入了CObjFactory的构造函数 但在构造函数还没执行完毕的时候发生了context switch 这时候对象的成员变量没有完全构造完成
第二个线程抢占了执行权 这就有可能访问到尚未构造完成的成员变量 后果可想而知
而二个Singleton的实现 自己对照第一种方式来解释 也将产生一样的问题
造成bug的关键点在于构造函数是否完成没有一个明确的标识 不建议使用static 对象的方式来进行Singleton实现
如果使用指针 根据指针是否为空则可以明确判断构造函数是否调用完成
//remark reference from http://www.cppblog.com/ant/archive/2007/09/07/31786.html
Double-Checked Locking机制看起来像是一个完美的解决方案,但是在某些条件下仍然不行。简单的说,编译器为了效率可能会重排指令的执行顺序(compiler-based reorderings)。看这一行代码:
_instance = new Singleton();
在编译器未优化的情况下顺序如下:
1.new operator分配适当的内存;
2.在分配的内存上构造Singleton对象;
3.内存地址赋值给_instance。
但是当编译器优化后执行顺序可能如下:
1.new operator分配适当的内存;
2.内存地址赋值给_instance;
3.在分配的内存上构造Singleton对象。
当编译器优化后,如果线程一执行到2后被挂起。线程二开始执行并发现0 == _instance为false,于是直接return,而这时Singleton对象可能还未构造完成,后果...
上面说的还只是单处理器的情况,在多处理器(multiprocessors)的情况下,超线程技术必然会混合执行指令,指令的执行顺序更无法保障。关于Double-Checked Locking的更详细的文章,请看:
The "Double-Checked Locking is Broken" Declaration
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Singleton的析构问题
到此Singleton已经算比较完善了,但是依然算不上完美,因为到现在只是解决了多线程问题,加入了模板支持,对于KDL problem(The Dead Reference Problem)依然没法解决,可以说在实现Singleton模式时,最大的问题就是多个有依赖关系的Singleton的析构顺序。虽然Modern C++ Design中给出了解决方案,但是Loki的实现太过复杂,在此就不详细说明了,有兴趣的可以看看Modern C++ Design,当然了,Loki库中用策略模式实现的Singleton也很不错!
- 复杂的Singleton
- singleton 线程安全的singleton
- SINGLETON的滥用
- c# singleton 的改进
- 简简单单的singleton
- 一个真正的Singleton
- Singleton的安全实现!
- Singleton的JDBC驱动
- Singleton的Application Context
- 常用的Singleton写法
- J2EE里的Singleton
- J2EE里的Singleton
- J2EE里的Singleton
- Singleton的各种实现
- singleton的优缺点
- 有关singleton的资料
- Singleton 的使用实现
- 一个真正的Singleton
- 初始化参数文件
- BackboneJS框架的技巧及模式(1)
- Blender学习笔记10.2
- C++内存模型
- Android开发优化之——对界面UI的优化
- 复杂的Singleton
- C++中String类的截取字符串学习笔记
- 八皇后问题,求解的个数
- 最小不重复数(百度笔试题)
- Android开发优化之——从代码角度进行优化
- Oracle to_char格式化函数
- [LeetCode] Unique Binary Search Trees II
- 简单的jquery效果
- 深度学习:CD算法学习笔记