C++单例模式与线程安全
2013-11-07 21:21
351 查看
C++单例模式
单例模式的主要作用是去除全局变量,这个意义在设计模式或者相关的资料中都有比较详细的介绍。一、 单例常见实现方式
单例的实现方式比较常见的可以分为两个大类:类静态成员指针,函数静态变量。其中《设计模式》书中主要以类静态成员指针进行了讲解,而在《More effective c++》书中介绍了一种更高效的基于函数静态变量的实现方式,下面简单的对它们进行一下显示和总结。1.1 类静态成员指针实现示例
为了便于展示,将所有的实现都放到了头文件中,代码如下:1. 懒惰初始化实现
class CMemberSingleton
{
public:
~CMemberSingleton(void){}
staticCMemberSingleton* GetInstance();
private:
CMemberSingleton(void){}
staticCMemberSingleton *m_pInstance;
};
CMemberSingleton*CMemberSingleton::m_pInstance = NULL;
CMemberSingleton* CMemberSingleton::GetInstance()
{
if(NULL != m_pInstance)
{
m_pInstance= new CMemberSingleton;
}
returnm_pInstance;
}
2. 普通实现
class CMemberSingleton
{
public:
~CMemberSingleton(void){}
staticCMemberSingleton* GetInstance();
private:
CMemberSingleton(void){}
staticCMemberSingleton *m_pInstance;
};
CMemberSingleton*CMemberSingleton::m_pInstance = new CMemberSingleton;
CMemberSingleton*CMemberSingleton::GetInstance()
{
returnm_pInstance;
}
3. 总结
基于静态成员变量的单例实现,无法实现对于单例的销毁工作,当然直接提供一个DestoryInstance这种函数给使用者调用是可以,但是调用的时机却是很不好把握的。
1.2 函数静态变量实现示例
基于函数静态变量来实现单例可以解决1.1中基于类静态成员变量中实例销毁问题。示例代码如下:class CMemberSingleton
{
friendCMemberSingleton& GetInstance();
public:
~CMemberSingleton(void){}
private:
CMemberSingleton(void){}
};
CMemberSingleton& GetInstance()
{
staticCMemberSingleton instance;
returninstance;
}
当然根据个人喜好,你也可以将GetInstance写成类的静态函数,实现效果是一致的。
1.3 自动销毁的基于类静态成员单例实现
如果说你确实非常喜欢基于静态成员来实现单例,或者某些因素强制你必须使用静态成员,我们也还是可能借助下面的方法来实现自动销毁工作。class CMemberSingleton
{
public:
~CMemberSingleton(void){}
staticCMemberSingleton* GetInstance();
private:
CMemberSingleton(void){}
staticCMemberSingleton *m_pInstance;
classCGarbo
{
public:
~CGarbo()
{
if(NULL != CMemberSingleton::m_pInstance)
{
deleteCMemberSingleton::m_pInstance;
}
}
};
staticCGarbo m_garbo;
};
CMemberSingleton::CGarboCMemberSingleton::m_garbo = CMemberSingleton::CGarbo();
CMemberSingleton*CMemberSingleton::m_pInstance = NULL;
CMemberSingleton*CMemberSingleton::GetInstance()
{
returnm_pInstance;
}
二、 单例线程安全性
关于单例的实现方式上面已经进行了简单的介绍,如果我们不编写多线程代码,这一段的讨论你可以忽略。单例是线程安全的吗(注意我们只讨论单例的获取,也就是常见的GetInstance,至于单例对应类的成员函数线程安全性,此处不作讨论)?回答是否定的!单例不是线程安全的,如果你实现的单例被多个线程调用,那么你就要注意了,很可能在某个时间出现异常(通常是程序启动的时候了!)。下面用一个例子展示一下,示例代码如下:
1. 单例代码
classCMemberSingleton
{
public:
~CMemberSingleton(void);
static CMemberSingleton* GetInstance();
private:
CMemberSingleton(void);
static CMemberSingleton *m_pInstance;
};
CMemberSingleton*CMemberSingleton::m_pInstance = NULL;
CMemberSingleton::CMemberSingleton(void)
{
cout<<"construct CMemberSingleton"<<endl;
}
CMemberSingleton::~CMemberSingleton(void)
{
cout<<"destoryCMemberSingleton"<<endl;
}
CMemberSingleton*CMemberSingleton::GetInstance()
{
if (NULL == m_pInstance)
{
m_pInstance = newCMemberSingleton;
}
return m_pInstance;
}
2. 主函数代码
void* thread_func(void *param)
{
CMemberSingleton::GetInstance();
return NULL;
}
int main(char **argv, int argc)
{
int i = 0;
pthread_t pids[100] ={0};
for (i = 0; i < 3;++i)
{
pthread_create(&pids[i],NULL, thread_func, NULL);
}
for (i = 0; NULL !=pids[i].p; ++i)
{
void *p = NULL;
pthread_join(pids[i],&p);
}
system("pause");
return 0;
}
3. 某次的执行结果
图1
执行结果可以明显看出,我们需要的是单例,却实际构造了三次,所以单例不一定是线程安全的。
4. 最简单的解决办法
关于解决单例线程安全的办法也许有很多,但是很多情况你都不可避免的要通过线程同步的方式来实现,下面介绍一种不需要线程同步的安全的单例实现。代码如下:
class CMemberSingleton
{
public:
~CMemberSingleton(void);
static CMemberSingleton*GetInstance();
private:
CMemberSingleton(void);
static CMemberSingleton*m_pInstance;
};
CMemberSingleton* CMemberSingleton::m_pInstance = newCMemberSingleton;
CMemberSingleton::CMemberSingleton(void)
{
cout<<"constructCMemberSingleton"<<endl;
}
CMemberSingleton::~CMemberSingleton(void)
{
cout<<"destoryCMemberSingleton"<<endl;
}
CMemberSingleton* CMemberSingleton::GetInstance()
{
return m_pInstance;
}
关于运行的结果就不再上图了,原理大家也应该明白,类的静态成员会在main函数运行之间就进行初始化的操作,如果我们不把它初始化为NULL,而是直接初始化一个对象给它,那么在有线程访问时,它已经初始化完成了,所以不会有线程同步的问题了。
虽然这个办法很好的解决了多线程安全问题,但是关于单例对象的销毁工作,就需要额外的实现了,你喜欢提供DestoryInstance这种函数,还是采用1.3中的“垃圾工”来帮你完成销毁任务呢?
相关文章推荐
- C++ 线程安全的单例模式
- C++实现线程安全的单例模式
- C++线程安全的单例模式
- C++中的单例模式(懒汉模式、饿汉模式及线程安全问题)
- c++单例模式(线程安全)
- 单例模式——C++实现线程安全的单例
- 从C++单例模式到线程安全
- 从零开始学C++之模板(四):用模板实现单例模式(线程安全)、模板方式实现动态创建对象
- 【转】C++ 线程安全的单例模式
- C++ 线程安全的单例模式
- 单例模式——C++(线程安全)
- C++线程安全的单例模式
- C++ 线程安全的单例模式
- C++单例模式(线程安全、内存释放)
- C++ 线程安全的单例模式
- 从C++单例模式到线程安全详解
- C++线程安全的单例模式
- C++线程安全的单例模式实现
- C++ 线程安全的单例模式
- 线程安全的单例模式-以C++代码为例