singleton 模式的多线程安全创建

来源:互联网 发布:c语言指针和变量的区别 编辑:程序博客网 时间:2024/05/19 22:48

      单例模式是通过类的静态函数直接获取对象,并且通过静态变量的特性保证一个进程只有一个该对象。这种模式的类在UML 里与其他类关系通常只是表现为“依赖”关系而已,应该说这个模式可以在设计上一定程度上帮我们解耦。其通常设计如下:


class A{

public:

    static A* CreateInstance()

   {

      static A* pInstance =NULL;

    if( pInstance==NULL)

       pInstance= new A();


   return pInstance;

  } 

};


但createinstance 函数可能在多线程下出现 同时被new 的情况,这个就不符合我们的想法了。

为了在多线程下正确使用,改进如下: 


class A {


static A* CreateInstance()

{

 

      static A* pInstance =NULL;

    if( pInstance==NULL)

    {

         EnterCriticSection(&g_cs);

         if(pInstance==NULL)

            {

            pInstance = new A(); 

         }

       LeaveCriticSection(&g_cs);

   }

  return pInstance ;

};

 代码里 我们必须连续检查2次pInstance变量,因为第一次判断 与entercriticSection 之间 ,pInstance 的值是有可能变化的。

 

上面使用criticalSection 变量,太过繁琐,我们使用 Interlock 函数来简化处理:

class A{

public:

    static A* CreateInstance()

   {

   volatile    static A* pInstance =NULL;

    if( pInstance==NULL)

     {

              A * pnew = new A();

               if(InterlockedCompareExchangePointer((volatile PVOID *)&pInstance,pnew,NULL) !=NULL)
                { // 失败,表示别的线程抢在当前线程前创建了该对象
                    delete pnew;
                }

    } 

   return (static A*) pInstance; 

  } 

};


这个里我们再通过模板构建一个通用的singleton创建器:

template<class T>
class SingleCreator {

public:
    static T* CreateInstance()
    {

   volatile    static T* pInstance =NULL;

    if( pInstance==NULL)

     {

             T * pnew = new A();

               if(InterlockedCompareExchangePointer((volatile PVOID *)&pInstance,pnew,NULL) !=NULL)
                { // 失败,表示别的线程抢在当前线程前创建了该对象
                    delete pnew;
                }

    } 

   return (static T*) pInstance; 
    }
};


原创粉丝点击