目录
懒汉模式和饿汉模式
区别
示例
懒汉模式线程不安全
懒汉模式线程安全
懒汉模式内部静态变量线程安全
饿汉式线程安全
指的是在系统生命周期内,只产生一个实例。
懒汉模式和饿汉模式
分为懒汉式和饿汉式
区别
-
创建时机和线程安全
线程安全:多线程共享资源的过程中,线程安全通过同步机制保证各个线程正确执行。
懒汉式,比较懒,只有在用到的时候才去想我怎么才能用到,所以只有当要用到该对象时才去创建实例。线程不安全。
原因:懒汉式的实例是在使用的时候才去申请,这个时候如果还没有new 出来实例,恰好又有多个线程进来访问创建对象的话,就会有问题。
解决方法:加锁。
饿汉式,害怕自己饿着,所以在一开始就准备好自己需要的东西。所以是一运行程序,就创建实例。在线程还未创建之前就已经创建出了实例,所以一定是线程安全的。
- 执行效率
懒汉式,为保证线程安全,需要加同步锁,所以执行比饿汉式要慢一些。
- 内存使用
懒汉式,在需要的时候才去创建实例对象,不浪费内存;
饿汉式,一开始就去创建,会占据空间,浪费内存。
示例
懒汉模式线程不安全
//懒汉模式:线程不安全
SingleCase * SingleCase::m_SingleCase = NULL;
SingleCase * SingleCase::GetInstance()
{
if (m_SingleCase == NULL)
{
m_SingleCase = new SingleCase();
}
return m_SingleCase;
}
创建5个线程,运行结果:
构造了三次,线程不安全,适合单线程使用
注:可以将构造、析构、拷贝赋值和拷贝构造都改为private,禁止其他类进行操作。
懒汉模式线程安全
//懒汉模式,线程安全
SingleCase * SingleCase::m_SingleCase = NULL;
std::mutex SingleCase::m_mutex;
SingleCase * SingleCase::GetInstance()
{
if(m_SingleCase == NULL)
{
//双检锁
//假如线程1和线程2同时到达
m_mutex.lock();
//此时线程1进入,判断m_SingleCase为空
if (m_SingleCase == NULL)
{
//实例化对象
m_SingleCase = new SingleCase();
}
//结束后,释放锁,此时线程2进入,m_SingleCase已经被实例化,可以避免多次实例
m_mutex.unlock();
}
return m_SingleCase;
}
双检锁
1.第一层if判断,完成实例化之后,之后的线程不需要进入等待,提高了效率;
2.第二层if判断,防止对象被多次实例化。
运行结果:
懒汉模式内部静态变量线程安全
//懒汉模式内部静态
SingleCase & SingleCase::GetInstance()
{
static SingleCase single;
return single;
}
运行结果:
饿汉式线程安全
SingleCase * SingleCase::m_SingleCase = new SingleCase();
SingleCase * SingleCase::GetInstance()
{
return m_SingleCase;
}
运行结果: