实现一个线程安全的单例模式

一、单例模式

       单例模式也叫单件模式。Singleton是一个非常常用的设计模式,几乎所有稍微大一些的程序都会使用它,所以构建一个高效的Singleton很重要。

1、单例类保证全局只有一个唯一实例对象

2、单例类提供获取这个唯一实例的接口。

        我们都能想到一个简单的单例模式该怎样实现:构造函数声明为private或protec防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例。

先看一段代码

class Singleton
{
public:
	//获取唯一对象实例的接口函数
	static Singleton* GetInstance()
	{
		if(_sInstance==NULL)
		{
			_sInstance=new Singleton();
		}
		return _sInstance;
	}
	//删除示例对象
	static void DelInstance()
	{
		if(_sInstance)
		{
			delete _sInstance;
			_sInstance=NULL;
		}
	}
	void Print()
	{
		cout<<_data<Print();
	TestSingleton::DelInstance;
}
        这个方法简单易懂,但是它是线程不安全的,如果两个线程同时调用_sInstance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误。当然我们也有线程安全的实现方法。

二、懒汉模式与饿汉模式
       单例大约有两种实现方法:懒汉与饿汉。

       *懒汉:顾名思义,不到万不得已就不回去实例化,也就是说在第一次用到类实例的时候才回去实例化。

       *饿汉:与懒汉相反,它是饥不择食的,所以在单例类定义的时候就进行实例化。

        两者的特点与选择要点:

       *由于要进行线程同步,所以在访问量较大,或者可能访问的线程较多时采用饿汉实现,可以实现更好的性能。这是以空间换时间。

       *在访问量较小时,可以实现懒汉模式。这是以时间换空间。

三、线程安全的的懒汉模式

       *方法一:加锁的经典懒汉实现:

class singleton
{
protected:
	singleton()
	{
		pthread_mutex_init(&mutex);
	}
private:
	static singleton* p;
public:
	static pthread_mutex_t mutex;
	static singleton* instance();
};
pthread_mutex_t singleton::mutex;
singleton* singleton::p=NULL;
singleton* singleton::instance()
{
	if(p==NULL)
	{
		pthread_mutex_lock(&mutex);
		if(p==NULL)
		{
			p=new singleton();
		}
		pthread_mutex_unlock(&mutex);
	}
	return p;
}
       *方法二:内部静态变量的懒汉实现

这个方法也比较简单,在instance函数里定义一个静态的实例,也可以保证拥有唯一实例,在返回时只需要返回其指针就可以了。

class singleton
{
protected:
	singleton()
	{
		pthread_mutex_init(&mutex);
	}
public:
	static pthread_mutex_t mutex;
	static singleton* instance();
	int a;
};
pthread_mutex_t singleton::mutex;
singleton* singleton::instance()
{
	pthread_mutex_lock(&mutex);
	static singleton obj;
	pthread_mutex_unlock(&mutex);
	return &obj;
}

四、饿汉模式

        线程安全本来就是安全的,不用加锁,因为在饿汉模式下,在单例类定义时就已经定义了一个对象,对类进行了初始化。后面不管哪个线程调用函数instance(),都只不过时返回一个对象的指针而已。所以是线程安全的,不需要在成员函数instance中加锁。

class singleton
{
protected:
	singleton()
	{}
private:
	static singleton* p;
public:
	static singleton* initance();
	int a;
};
singleton* singleton::p=new singleton;
singleton* singleton::initance()
{
	return p;
}
int main()
{
	singleton* s=singleton::instance();
	s->a=10;
	return 0;
}




你可能感兴趣的:(总结)