下面是一个简单的单例模式
构造函数声明为private或protect防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例。
class singleton
{
private:
singleton(){}
private:
static singleton* p;
public:
static singleton* instance();
};
singleton* singleton::p = NULL;
singleton* singleton::instance()
{
if (p == NULL)
p = new singleton();
return p;
}
但是该方法并不是线程安全的,考虑两个线程同时首次调用instance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误!同时,这也不是单例的唯一实现!线程安全的单例模式有两种经典叫法:懒汉模式和恶汉模式
1. 懒汉模式:不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化;
2. 饿汉模式:在单例类定义的时候就进行实例化;
特点与选择:
1)由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
2)在访问量较小时,采用懒汉实现。这是以时间换空间。
1.懒汉模式
方法1:加锁的经典懒汉实现:
class singleton
{
private:
singleton(){
pthread_mutex_init(&mutex);
}
private:
static singleton* p;
public:
static pthread_mutex_t mutex;
static singleton* initance();
};
pthread_mutex_t singleton::mutex;
singleton* singleton::p = NULL;
singleton* singleton::initance()
{
if (p == NULL)
{
pthread_mutex_lock(&mutex);
if (p == NULL)
p = new singleton();
pthread_mutex_unlock(&mutex);
}
return p;
}
2.饿汉模式
class singleton
{
private:
singleton(){ }
private:
static singleton* p;
public:
static singleton* initance();
};
singleton* singleton::p = new singleton;
singleton* singleton::initance()
{
return p;
}