设计模式之单例模式

上篇我们讲了工厂模式,这章我们来聊聊单例模式,单例模式也是最常用的模式之一

在这篇里我要讲到懒汉式单例(经典单例)和饿汉式单例,以及经典单例的修改等。


经典单例:

以下代码在VS2012上编译通过

.h文件

class singleton
{
private:
 singleton();
 static singleton* mInstance;
public:
 static singleton* getInstance();
};

.cpp文件

singleton::singleton()
{
}

singleton* singleton::getInstance()
{
 if(mInstance==NULL)
 {
  mInstance=new singleton();
 }
 return mInstance;
}

singleton* singleton::mInstance=NULL;


 

调用文件:

int _tmain(int argc, _TCHAR* argv[])
{
	singleton* instance= singleton::getInstance();
	singleton* instance2= singleton::getInstance();
	if(instance==instance2)
	{
	cout<<"The same"<<endl;
	}
	return 0;
}
执行结果:

The same

       在上面我们可以看到经典单例模式的构造过程:首先要该类不被其他外部调用实例化,就要将构造函数设为私有权限,然后又通过公共的静态方法来实例化这个类,返回实例化后的对象的指针,然后通过内部私有指针mInstance来保存这个返回的指针,这样我们就可以使用这个类了。但是怎么来保证这个实例的唯一性呢?我们在静态方法getInstance()中要先判断,如果mInstance是为NULL的(mInstance要初始化为NULL),那么我们才实例化这个类。


问题:以上的单例模式如果在多线程中会怎么样呢?

    我们可以想想这种情况,如果线程1在进入了if(mInstance==NULL) 这个判断区域内的时候,要去实例化类,这个过程中要对新的实例各种初始化完之后才将新的实例的内存地址赋值给mInstance,也就是说这段时间内,mInstance也是等于NULL的,如果这个时候线程2再来实例化一次,还是能进入if(mInstance==NULL) 这个判断区域内的。所以最终我们就得到了两个不一样的实例,这显然是有悖于单例模式初衷的。


解答:方法一,任何一个线程可以在进入if(mInstance==NULL)之前加锁,然后出来后解锁。 方法二,饿汉单例模式


饿汉单例模式:

为什么称为饿汉单例模式呢?本质上就是刚创建这个类的时候就实例化这个类了,而不是要用到的时候再去实例化,既然使用过程中没有创建新的实例,自然就不可能有两个实例了。


h文件
class singleton
{
private:
 singleton();
 static singleton* mInstance;
public:
 static singleton* getInstance();
};

.cpp文件

singleton::singleton()
{
}

singleton* singleton::getInstance()
{
 return mInstance;
}

singleton* singleton::mInstance=new singleton();

       由以上可以看出饿汉单例模式,每次getInstance()的调用过程中,完全没有实例化的操作,从根本上杜绝了两个实例的现象。虽然一开始就要占一点内存,不过在多线程中利比弊大多了,好了今天就写到这里了,肚子饿了。。。饿汉+1偷笑


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值