单例模式:懒汉式和饿汉式

目录

懒汉模式和饿汉模式

区别

示例

懒汉模式线程不安全

懒汉模式线程安全

 懒汉模式内部静态变量线程安全

饿汉式线程安全


指的是在系统生命周期内,只产生一个实例。

懒汉模式和饿汉模式

分为懒汉式饿汉式

区别

  • 创建时机和线程安全

线程安全:多线程共享资源的过程中,线程安全通过同步机制保证各个线程正确执行。

懒汉式,比较懒,只有在用到的时候才去想我怎么才能用到,所以只有当要用到该对象时才去创建实例。线程不安全

原因:懒汉式的实例是在使用的时候才去申请,这个时候如果还没有new 出来实例,恰好又有多个线程进来访问创建对象的话,就会有问题。

解决方法:加锁。

饿汉式,害怕自己饿着,所以在一开始就准备好自己需要的东西。所以是一运行程序,就创建实例。在线程还未创建之前就已经创建出了实例,所以一定是线程安全的。

  • 执行效率

懒汉式,为保证线程安全,需要加同步锁,所以执行比饿汉式要慢一些。

  • 内存使用

懒汉式,在需要的时候才去创建实例对象,不浪费内存;

饿汉式,一开始就去创建,会占据空间,浪费内存。

示例

懒汉模式线程不安全

//懒汉模式:线程不安全
SingleCase * SingleCase::m_SingleCase = NULL;

SingleCase * SingleCase::GetInstance()
{
	if (m_SingleCase == NULL)
	{
		m_SingleCase = new SingleCase();
	}
	return m_SingleCase;
}

创建5个线程,运行结果:

构造了三次,线程不安全,适合单线程使用

单例模式:懒汉式和饿汉式_第1张图片

注:可以将构造、析构、拷贝赋值和拷贝构造都改为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判断,防止对象被多次实例化。

运行结果:

单例模式:懒汉式和饿汉式_第2张图片

懒汉模式内部静态变量线程安全

//懒汉模式内部静态
SingleCase & SingleCase::GetInstance()
{
	static SingleCase single;
	return single;
}

运行结果:

单例模式:懒汉式和饿汉式_第3张图片

饿汉式线程安全

SingleCase * SingleCase::m_SingleCase = new SingleCase();
SingleCase * SingleCase::GetInstance()
{
	return m_SingleCase;
}

运行结果:

单例模式:懒汉式和饿汉式_第4张图片

你可能感兴趣的:(设计模式,单例模式,开发语言,c++)