Linux---单例模式

什么是单例模式

单例模式是设计模式的最简单的形式之一。这个模式的最主要目的是使得类的一个对象称为系统中唯一的实例。

单例模式的特点

一个类只有一个对象。
例如:一夫一妻制。

单例模式的分类

  • 饿汉模式:在创建对象的时候,直接分配资源,当对象想要使用资源的时候,立即可以使用。
  • 懒汉模式:在创建对象时不分配资源,当该对象需要资源时,再分配资源。
    例如:我们在逛超市的时候,有可能会买好几天的东西放在冰箱里,这样当我们需要的时候直接从冰箱里拿就可以,这就属于饿汉模式。
    当我们需要的时候,再去超市买,这就是懒汉模式。

我们可以考虑一下:我们在打游戏的时候,由于游戏资源非常的大,所以不可能一次性将所有的游戏数据加载到CPU上,有种“延时加载”的思想(懒汉模式)。反之,当在启动时,将所需的资源准备好的,属于“及时加载”的思想(饿汉模式)

饿汉模式

饿汉模式怎么实现创建对象时,立即分配资源呢?
用static关键字实现。
static关键字讲解

template<class T>
class Single_Starve
{
public:
	static T *GetData()
	{
		return &_data;
	}
private:
	static T _data;
};

饿汉模式是线程安全的,在类的创建时同时实例化一个静态的实例。

懒汉模式

由于懒汉模式是在实际使用资源的时候才会主动申请资源。

template<class T>
class Singel_Slacker
{
public:
	static T *GetData()
	{
		_mutex.lock(); //加锁操作
		if(_data == NULL)
			_data = new T();
		_mutex.unlock(); //解锁操作
		return _data;
	}
private:
	volatile static T* _data; //这里只是申请了保存资源地址的空间
	static std::mutex _mutex; //调用mutex库函数,定义锁资源
};

volatile关键字:防止编译器过度优化。
担心编译器对代码进行优化,使得数据直接从寄存器中取,会造成数据逻辑混乱,所以使用volatile关键字。

由于懒汉模式是在使用资源的时候,才申请资源,所以会出现线程安全问题,因此在申请资源的时候,需要进行加锁操作,申请完资源后,需要解锁。

但是上面代码有锁冲突的概率

那什么是锁冲突
当_data = NULL时,A线程运行时,先进行加锁操作,这时B线程也过来了,等待锁资源,当A操作完成后,现在_data 已经不为NULL,A释放锁资源,这时处于等待队列中的线程B进行加锁操作,加完锁后发现_data已经不为NULL,则返回A申请的资源后才解锁,这样无用的操作,就会降低效率。

template<class T>
class Singel_Slacker
{
public:
	static T *GetData()
	{
		if(_data == NULL)  //双判断,降低锁冲突
		{
			_mutex.lock(); //加锁操作
			if(_data == NULL)
				_data = new T();
			_mutex.unlock(); //解锁操作
		}
		return _data;
	}
private:
	volatile static T* _data; //这里只是申请了保存资源地址的空间
	static std::mutex _mutex; //调用mutex库函数,定义锁资源
};

懒汉模式是延迟加载思想,面对多线程访问的时候,需要进行加锁操作,实现同步,为了增加效率,降低锁冲突,则需要进行二次判断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值