单例模式是通过类的静态函数直接获取对象,并且通过静态变量的特性保证一个进程只有一个该对象。这种模式的类在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;
}
}
}
};