1.懒汉模式
在第一次用到类实例的时候才会去实例化
-
方法1:加锁的经典懒汉实现
class singleton
{
protected:
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:内部静态变量的懒汉实现
在instance函数里定义一个局部的静态实例,只在第一次运行时创建,所以也可以保证拥有唯一实例。
这里最好加上锁,如不加,可能造成线程不安全(depends on implementation: e.g. g++ will insert locks, but MSVC will not)。
class singleton
{
protected:
singleton()
{
pthread_mutex_init(&mutex);
}
public:
static pthread_mutex_t mutex;
static singleton* initance();
int a;
};
pthread_mutex_t singleton::mutex;
singleton* singleton::initance()
{
pthread_mutex_lock(&mutex);
static singleton obj;
pthread_mutex_unlock(&mutex);
return &obj;
}
2.饿汉模式
在进入main函数前就已经完成对象的定义和初始化,线程安全。
但是有隐患,因为c++中对全局对象的构造顺序并没有明确的规定。假如有一个全局对象A,其构造函数里引用如下代码饿汉形式的指针,若在A构造函数构造之前以上单例并未构造出来,那就会有问题。
同时要注意,在构造函数里使用其它类的成员变量,是危险行为。
class singleton
{
protected:
singleton()
{}
private:
static singleton* p;
public:
static singleton* initance();
};
singleton* singleton::p = new singleton;
singleton* singleton::initance()
{
return p;
}
3.单例模式的资源释放
很多情况下资源的释放是有必要的,如关闭占用的文件、断开与服务器的连接等等。
没有使用new时,只需要在析构函数中释放相关资源即可;
使用了new时,不能在析构函数中delete单例,这样会造成delete和析构函数的循环调用,可以使用以下方法:
- 法1:写一个函数,主动delete,缺点是容易忘记调用该函数。
- 法2:利用C++ Rall机制(resource acquisition is initialization,资源获取即初始化),没有深究到底是啥,大概就是程序在结束的时候,系统会自动析构所有的全局变量,以及所有类的静态成员变量。使用一个嵌套类,并定义一个私有的静态成员变量,在类的析构函数中delete单例指针。
class CSingleton:
{
public:
static CSingleton * GetInstance();
protected:
CSingleton();
private:
static CSingleton * m_pInstance;
class CGarbo // 它的唯一工作就是在析构函数中删除CSingleton的实例
{
public:
~CGarbo()
{
if (CSingleton::m_pInstance){
delete CSingleton::m_pInstance;
CSingleton::m_pInstance = nullptr;
}
}
};
static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数
}
参考:
https://www.cnblogs.com/qiaoconglovelife/p/5851163.html
https://stackoverflow.com/questions/1463707/c-singleton-vs-global-static-object