单例模式是一种对象创建模式,使用单例模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。保证一个类只有一个实例,同时提供能对该实例访问的全局访问方法。
为什么使用单例模式
- 多线程之间,比如初始化一次socket资源
- 比如servlet(是使用 Java 语言编写的运行在服务器端的程序。),共享同一个资源或者操作同一个对象。
- 在整个程序空间使用全局变量,共享资源
- 大规模系统中,为了性能的考虑,需要节省对象的创建时间等等
懒汉式
在程序一开始时,是没有创建单例对象的,而是在使用的时候,才去创建对象。
注意:懒汉式在每次实例前都要判断是否已经实例过了,在多线程当中多个线程会多次创建单例对象,因此要避免这种操作。
#include <iostream>
using namespace std;
class Singleton
{
private:
Singleton()
{
cout << "Singleton 构造函数" << endl;
}
public:
static Singleton*GetInstance()//
{
cout << "懒汉式 单例模式" << endl;
if (m_instance == NULL)
m_instance = new Singleton();//使用时创建对象
return m_instance;
}
static void FreeSingleton()
{
if (m_instance != NULL)
{
delete m_instance;
m_instance = NULL;
}
cout << "FreeSingleton 释放内存" << endl;
}
private:
static Singleton* m_instance;
};
Singleton* Singleton::m_instance = NULL;
int main()
{
Singleton *s = Singleton::GetInstance();
Singleton::FreeSingleton();
system("pause");
return 0;
}
饿汉式
与懒汉式正好相反,在程序一开始时,就已经存在了单例对象。
注意:饿汉式不管你创不创建实例,都会先创建出来。
#include <iostream>
using namespace std;
class Singleton
{
private:
Singleton()
{
cout << "Singleton 构造函数" << endl;
}
public:
static Singleton*GetInstance()
{
cout << "饿汉式 单例模式" << endl;
return m_instance;
}
static void FreeSingleton()
{
if (m_instance != NULL)
{
delete m_instance;
m_instance = NULL;
}
cout << "FreeSingleton 释放内存" << endl;
}
private:
static Singleton* m_instance;
};
Singleton* Singleton::m_instance = new Singleton();//一开始就创建好了
int main()
{
Singleton *s = Singleton::GetInstance();
Singleton::FreeSingleton();
system("pause");
return 0;
}
在多线程下的单例模式
- 懒汉模式虽然有优点,但每次调用都要判断是否实例过了,使程序相对开销增大。
- 多线程中会导致多个实例的产生,从而导致运行代码不正确以及内存的泄漏。
C++构造函数并不是线程安全的,构造函数的执行需要两步,第一步先分配内存,第二步初始换成员变量。在这里由于多线程的竞争,可能当我们分配好内存以后,还没来得及初始化成员变量,就进行线程切换了,另外一个线程拿到所有权后,由于内存已经分配了,但是变量初始化还没进行,因此打印成员变量的相关值会发生不一致的现象。
多线程先抛出,以后会专门来讲。