单例模式(Singletion):保证一个类仅有一个实例,并提供一个访问该实例的全局访问点。
单例模式主要作用是保证唯一的实例,可以严格地控制客户端怎样访问该实例以及何时访问它。可以简单的理解为对唯一实例的受控访问。
Singleton类作为我们要进行单例操作的类,在类中定义一个静态的GetInstance操作函数,允许客户端访问其唯一实例,主要用于创建自己的唯一实例。
class Singleton
{
public:
static Singleton* GetInstance()
{
if (Instance == null)
{
Instance = new Singleton();
}
return Instance;
}
private:
Singleton();
static Singleton *Instance;
};
Singleton *Singleton::Instance = NULL;
客户端调用
Singleton *instance = Singleton::GetInstance();
以上为简单的单例模式的示例,在单线程程序中可以很好的完成任务。而当我们的程序为多线程时就可能出现问题。
在多线程程序中,当多个线程同时访问GetInstance()时就可能产生多个实例。因此在多线程程序中需要对我们的单例类进行进一步的完善:
mutex m;
class Singleton
{
public:
static Singleton* GetInstance()
{
if (Instance == NULL)
{
m.lock();
if(Instance == NULL) //互斥量,双重判断机制
{
Instance = new Singleton();
}
m.unlock();
}
return Instance;
}
private:
Singleton();
static Singleton *Instance;
};
Singleton *Singleton::Instance = NULL;
class Singleton
{
public:
//get 方法
static Singleton * getInstance(){
//返回一个实例化的对象
return instance;
}
private:
//声明一个静态的实例
static Singleton *instance;
//私有构造函数
Singleton(){
}
};
//每次先直接实例化instance,get 方法直接返回这个实例
Singleton * Singleton::instance = new Singleton();
这种静态初始化方式只在类被加载的时候将类实例化,因此被称为饿汉式单例模式。之前的两种写法都是在第一次被引用的时候才会将类实例化,因此被称为懒汉式单例模式。静态初始化实例可以保证线程安全,因为静态实例初始化在程序开始时进入主函数之前,就由主线程以单线程方式完成了初始化!饿汉式的单例类,也就是静态初始化实例保证其线程安全性,故在性能需求较高时,应使用这种模式,避免频繁的锁争夺。
饿汉式单例模式在程序加载该类的时候就对类进行了初始化,这时候我们可能并不会马上使用,所以会提前占用系统的资源。但是懒汉式单例模式则需要考虑多线程不安全问题,对类实例化的过程进行双重加锁以保证实例化的安全。两种方式各有好处,具体需要根据我们在开发的时候根据应用的具体场景需求选择最佳的单例模式。