什么是单例模式
一个类只能创建一个对象,即单例模式,该模式下可保证系统中该类只有一个实例,并提供一个访问它的全局接口,该实例被所有程序模块共享。
单例模式有两种实例情况
- 饿汉模式:程序启动就创建一个唯一的实例对象
- 懒汉模式:调佣全局接口的时候创建唯一的实例。
饿汉模式
cpp
class Singleton
{
public:
static Singleton* GetInstance()
{
return _ins;
}
void Add(const string& str)
{
_mtx.lock();
_v.push_back(str);
_mtx.unlock();
}
void Print()
{
_mtx.lock();
for (auto& e : _v)
{
cout << e << endl;
}
cout << endl;
_mtx.unlock();
}
private:
//限制类外随意创建对象
Singleton()
{
}
private:
int _n;
vector<string> _v;
mutex _mtx;
static Singleton* _ins;
};
Singleton* Singleton::_ins = new Singleton;
但是饿汉有一个问题:如果单例对象十分耗时或者占用很多资源,比如加载插件,初始化网络连接,也有可能在程序一开始用不到,那么在程序一开始创建就会导致程序启动很慢,所以有了懒汉模式。
懒汉模式
cpp
class Singleton
{
public:
static Singleton* GetInstance()
{
//双检查加锁
if (_ins == nullptr) //提高效率,不需要每次加锁和解锁
{
_imtx.lock();
if (_ins == nullptr) //保证线程安全,只用new一次
{
_ins = new Singleton;
}
_imtx.unlock();
}
return _ins;
}
void Add(const string& str)
{
_vmtx.lock();
_v.push_back(str);
_vmtx.unlock();
}
void Print()
{
_vmtx.lock();
for (auto& e : _v)
{
cout << e << endl;
}
cout << endl;
_vmtx.unlock();
}
private:
//限制类外随意创建对象
Singleton()
{
}
private:
int _n;
vector<string> _v;
mutex _vmtx;
static mutex _imtx;
static Singleton* _ins;
};
Singleton* Singleton::_ins = nullptr;
mutex Singleton::_imtx;
这里注意一下,创建实例的时候要用双重加锁,因为在多线程的场景下,就去一直加锁判断,要知道锁的消耗是很大的,所以双重检查是很重要的。
懒汉模式的优点:
- 第一次使用的时候创建实例对象
- 如果多个单例对象有启动顺序要求的话,也可以控制(这点饿汉模式就无法控制了)
懒汉模式的缺点
- 复杂