1.单例模式是设计模式的一种:一个对象只能被实例化一次
2.单例模式有饿汉和懒汉两种实现方式:
- 饿汉:程序初始化时进行实例化,因为资源已经全部加载,因此运行速度比较快,流畅。缺点是初始化的时候耗时比较长。
- 懒汉:程序资源使用的时候再进行加载,对象使用的时候再实例化,初始化加载比较快,但是运行流畅度不够。
饿汉方式实现单例模式
template<typename T>
class Singleleton{
static T data;
public:
static T* GetInstance(){
return &data;
}
};
只要通过Singleton这个包装类来使用T对象,则一个进程中只有一个T对象的实例。
懒汉方式实现单例模式
template<typename T>
class Singleton{
static T* inst;
public:
static T* GetInstance(){
if(inst==NULL){
inst=new T();
}
return inst;
}
};
存在一个严重的问题,线程不安去。
第一次调用GetInstance的时候,如果两个线程同时调用,可能会创建出两份T对象的实例。
懒汉方式实现单例模式(线程安全版本)
template<typename T>
class Singleton{
volatile static T* inst; //需要设置volatile关键字,否则可能被编译器优化。
static std::mutex lock;
public:
static T* GetInstance(){
if(inst==NULL){ //双重判定空指针,降低锁冲突的概率,提高性能。
lock.lock(); //使用互斥锁,保证多线程情况下也只能调用一次new
if(inst==NULL){
inst=new T();
}
lock.unlock();
}
return inst;
}
};
注意:
- 加锁解锁的位置
- 双重if判定,避免不必要的锁竞争
- volatile关键字防止过度优化