单例模式介绍
单例模式(Singleton),也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。
单例模式注意点 ##
1>只能实例化一个对象
2>构造函数私有化,这样在类外就不能另外new对象
2>多线程的时候注意加锁
优缺点
优点:.
1>由于在系统内存中只存在一个对象,因此可以 节约系统资源,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
2>避免对共享资源的多重占用.
缺点:
1>不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
2>由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
代码实现:
class CSingleton
{
private:
CSingleton() //构造函数是私有的
{
}
static CSingleton *m_pInstance;
public:
static CSingleton * GetInstance()
{
if(m_pInstance == NULL) {//判断是否是第一次调
m_pInstance = new CSingleton();
}
return m_pInstance;
}
};
用户访问唯一实例的方法只有GetInstance()成员函数。如果不通过这个函数,任何创建实例的尝试都将失败,因为类的构造函数是私有的。也就是说GetInstance的返回值是当这个函数首次被访问时被创建的。这是一种防弹设计——所有GetInstance()之后的调用都返回相同实例的指针
上诉代码在多线程的环境下却不行了,因为很可能两个线程同时运行到if (m_pInstance == NULL)这一句,导致可能会产生两个实例。于是就要在代码中加锁。
static CSingleton * GetInstance()
{
Lock();
if(m_pInstance == NULL) {//判断是否是第一次调
m_pInstance = new CSingleton();
}
Unlock();
return m_pInstance;
}
但这样写的话,有经验的人一眼就看出,这样会对性能有很大的影响,因为每次判断是否为空都需要被锁定,如果有很多线程的话,就爱会造成大量线程的阻塞。于是又有一种写法叫双重锁定。
static CSingleton * GetInstance()
{
if (m_pInstance == NULL) {
Lock();
if (m_pInstance == NULL) {
m_pInstance = new CSingleton();
}
Unlock();
}
return m_pInstance ;
}
这样只够极低的几率下,通过越过了if (m_pInstance == NULL)的线程才会有进入锁定临界区的可能性,这种几率还是比较低的,不会阻塞太多的线程,但为了防止一个线程进入临界区创建实例,另外的线程也进去临界区创建实例,又加上了一道防御if (m_pInstance == NULL),这样就确保不会重复创建了。