线程安全的单例模式
应用场景:一个类只能实例化一个对象;一份资源只能被加载一次。向外提供一个统一的接口,用于访问。
具体实现:饿汉方式
/ 懒汉方式
举例简单理解饿汉 / 懒汉方式:
饿汉方式:吃完饭后立马洗碗,这样下次到饭点就可以直接吃饭(资源提前加载)
懒汉方式:吃完饭后不洗碗,放着,到下次吃饭时再洗碗(资源在使用时才加载)
饿汉方式
饿汉方式:资源在程序初始化阶段就完成加载—空间换时间
注意:饿汉方式的特性决定了它不需要考虑线程安全
的问题。
1、静态修饰资源:保证资源只有一份,并且在程序初始化阶段完成初始化加载
2、构造函数私有化:保证一个类只能实例化一个对象
代码实现:
template<class T>
class Signaleton{
private:
static T _data; //静态修饰资源
Signaleton(){} //构造函数私有化
public:
T* Getinstance()
{
return &_data;
}
};
懒汉方式
懒汉方式:资源需要使用时再去加载—延迟加载,节省资源
实现:
1、定义对象指针;保证资源不会在初始化时加载
2、静态修饰;保证操作同一资源
3、volatile修饰;保持内存可见性,防止编译器过度优化
4、线程安全;加锁保护
5、外部二次检测;避免锁冲突提高效率
6、构造函数私有化;保证一个类只能实例化一个对象
template<class T>
class Signaleton{
private:
volatile static T *_data;
static std::mutex _mutex; //互斥锁
public:
volatile static T* Getinstance()
{
if(_data==NULL) //外部检测
{
_mutex.lock(); //加锁
if(_data==NULL) //内部检测
{
_data=new T();
}
_mutex.unlock(); //解锁
}
return _data;
}
};