多线程Singleton单件模式

多线程Singleton单件模式

Singleton模式是最简单的模式,比较汗颜的是自己一直以来使用的是单线程的Singleton模式,最近在听了李建忠老师的模式讲座录像后,才发现自己一直没注意到这点。这个录像讲座在后面给出了链接地址: C#面向对象设计模式纵横谈(2):Singleton 单件(创建型模式)

下面内容整理自李建忠老师的讲课内容:

单线程的Singleton模式

public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton Instance { get { if (instance == null) instance = new Singleton(); return instance; } } }

要点:

  • Singleton模式中的实例构造器可以设置为protected以允许子类派生。
  • Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
  • Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样跟Singleton模式的初衷违背。
  • Singleton模式只考虑到了对象创建的管理,并没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。
  • 上述代码不支持多线程环境,上述代码在多线程下,仍然有可能得到Singleton类的多个实例。

多线程的Singleton模式

public class Singleton { private static volatile Singleton instance = null; private static object lockHelper = new object(); private Singleton() { } public static Singleton Instance { get { if (instance == null) { lock (lockHelper) { if (instance == null) { instance = new Singleton(); } } } return instance; } } }

代码说明:

  • volatile C#关键字作用,简单来说,编译器编译我们的代码时候,会对代码作一些优化,进而对代码进行了微调,使用volatile关键字就可以避免这个微调。继而严格意义上保证不会产生多线程。更详细的关于volatile 的说明,请看参考资料。
  • 双检查加锁模式。在lock之外和之内,我们做了instance是否为空的检查。这叫双检查。因为同步控制的时间太长了。双检查能够最高效地实现多线程安全的访问。

使用.net特有的支持多线程的单件模式代码

public sealed class Singleton { public static readonly Singleton Instance = new Singleton(); private Singleton() { } }

代码说明:

  • sealed 修饰符表示该类是密封类,不能被继承。你可以按需修改。
  • 这里readonly关键字只是不希望客户程序将Instance字段设置为null等不合理的值。
  • *** static *** = new Singleton(); 是使用了内联初始化技术,这部分初始化其实是在static Singleton()中执行的。即上面的代码相当于:

    public sealed class Singleton { public static readonly Singleton Instance; static Singleton() { Instance = new Singleton(); } private Singleton() { } }

  • 上述代码在编译时,会使用一个名为beforefieldinit元数据标志。此标志使得运行库能够在任何时候执行类型构造函数方法,只要该方法在第一次访问该类型的静态字段之前执行即可。换句话说,beforefieldinit 为运行库提供了一个执行主动优化的许可。如果没有 beforefieldinit,运行库就必须在某个精确时间运行类型构造函数,即,恰好在第一次访问该类型的静态或实例字段和方法之前。
  • 静态构造器自身就可以保证,多线程情况下,系统就可以保证只有一个执行。

缺点:

  • 不支持参数化单件构造器。即静态构造器不支持参数,就导致我们无法利用静态构造器实现传参数的单件。

 

参考资料:

讲讲volatile的作用

http://blog.21ic.com/user1/2949/archives/2007/35599.html

Implementing the Singleton Pattern in C#

http://www.yoda.arachsys.com/csharp/singleton.html

初始化内联引用类型静态字段

http://msdn.microsoft.com/zh-cn/library/ms182275.aspx

通过七个关键编程技巧得益于静态内容

http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/us0501StaticsinNET.mspx?mfr=true

模式设计c#--创建型--Singleton

http://www.cppblog.com/mzty/archive/2006/01/03/2384.html

 

 

-------------------------------------------------------------------------------------

载自:http://hghhe.blog.163.com/blog/static/32377568200961092014821/#comment=fks_083067083081081071086087083095087084082068083083080075

C++单件模式的实现 

单件模式:其实就是保证了一个类有且仅有一个对像,又提供一个全局访问方法。对某些类来说,希望它只有一个对像,那么用单件模式设计再好不过了。很多人在刚开始时不知道Ogre中getSingleton()、getSingletonPtr()是什么意思(我刚开始也不懂),其实它就是用了单件模式,用来获取实例指针。比如Ogre中的MeshManager、SceneManager等都使用了单件模式。

如何实现:简单来说,就是在类中添加一个返回类对像的方法(不存在对像则创建或用“new”来创建)。我的做

                  法是不用"new"来创建(把构造函数设为私有或保护类型),而在getSingletonPtr()中进行创建。

使用宏定义: 为了减少代码的重复量,适应更多的类,可以使用宏定义来实现。

                   例://************单件模式的声明**************

                          #define DECLARE_SINGLETON(T)\

                                       protected:\

                                       static T* handleT;\             //用于保存对像的指针

                                       static void deleteT();\        //删除对像函数

                                       T(){}\                                 //保护类型的构造函数,防止直接实例化

                                       public:\

                                        ~T(){deleteT();}\

                                        static T* getSingletonPtr();\            //返回唯一对像的指针

                          //************单件模式的实现**************

                          #define IMPLEMENT_SINGLETON(T)\

                                       T* T::handleT(NULL);\

                                       T* T::getSingletonPtr()\

                                       {\

                                              if(!handleT)\                              //如不存在对像则创建,否则直接返回对像指针

                                              {\

                                                     handleT = new T;\

                                               }\

                                               return handleT;\

                                       }\

                                       void T::deleteT()\                              //删除唯一对像

                                       {\

                                               if(handleT)\

                                               {\

                                                      delete handleT;\

                                               }\

                                       }

上面的代码可以放在头文件中(比如StdAfx.h文件),然后在要实现单件模式的类的.h声明文件中使用

DECLARE_SINGLETON(类名);在类的.cpp实现文件中使用IMPLEMENT_SINGLETON(类名)。                       

注:如果你是直接COPY上面的代码,在使用时应当把注释全部去掉,否则会编译出错(因为宏定义...)。

 

使用模版实现:使用模版类实现也是一个不错的方法,Ogre中的单件模式就是用模版类来实现的!!   

                          下面是Ogre中Singleton模版类的源代码:

                          template <typename T>

                          class Singleton

                          {

                             protected:

                                 static T* ms_Singleton;                //用于保存实例指针

                             public:

                                 Singleton( void )                          //初始化函数

                                {

                                   assert( !ms_Singleton );

                                   // 下面是判断VC++编译器版本,版本不同相应的处理也不同

                                   #if defined( _MSC_VER ) && _MSC_VER < 1200 

                                       int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;

                                       ms_Singleton = (T*)((int)this + offset);

                                   #else

                                       ms_Singleton = static_cast< T* >( this );

                                   #endif

                                }

                                ~Singleton( void )                         //析构函数

                                {  

                                   assert( ms_Singleton );

                                   ms_Singleton = 0; 

                                }

                               static T& getSingleton( void )         //返回实例

                               { 

                                   assert( ms_Singleton );

                                   return ( *ms_Singleton ); 

                               }

                              static T* getSingletonPtr( void )       //返回实例指针

                              {

                                  return ms_Singleton;

                              }

                      };

这个类怎么用呢?  这里假设我们的一个类"CMyClass"要使用单件模式,那么我们可以这样做:

class CMyClass : public Singleton<CMyClass >

{

    CMyClass() {}   //构造函数

    ~CMyClass() {} //析构函数,这里需要自己对实例进行释放

}

这样CMyClass 就继承了Singleton类中的方法,就可以直接用getSingleton()和getSingletonPtr()获取实例了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值