单例模式,用于确保一个类只有一个实例 ,并提供一个全局访问点以访问该实例。
饿汉式(Eager Initialization)
程序启动时就创建实例
cpp
#include <iostream>
class SingletonEager
{
private:
static SingletonEager* instance;
SingletonEager() {} // 私有构造函数
public:
static SingletonEager* getInstance() {
return instance;
}
};
SingletonEager* SingletonEager::instance = new SingletonEager; // 在程序启动时即创建实例
int main()
{
SingletonEager* instance1 = SingletonEager::getInstance();
SingletonEager* instance2 = SingletonEager::getInstance();
std::cout << (instance1 == instance2) << std::endl; // 输出 1,两个指针变量的内容相同
return 0;
}
懒汉式(Lazy Initialization)
延迟初始化,即在第一次访问时才创建实例。
缺点:不是线程安全的 。因为它没有考虑多线程同时访问的情况。如果多个线程同时调用 getInstance() 方法,并且在 instance 还没有被初始化之前,它们可能会同时进入条件 if (!instance) 中,导致多次创建实例,这违反了单例模式的要求。
c
#include <iostream>
class SingletonLazy
{
private:
static SingletonLazy* instance;
SingletonLazy() {} // 私有构造函数
public:
static SingletonLazy* getInstance()
{
if (!instance) {
instance = new SingletonLazy;
}
return instance;
}
};
SingletonLazy* SingletonLazy::instance = nullptr;
int main() {
SingletonLazy* instance1 = SingletonLazy::getInstance();
SingletonLazy* instance2 = SingletonLazy::getInstance();
std::cout << (instance1 == instance2) << std::endl; // 输出 1,两个指针变量的内容相同
return 0;
}
想要解决线程安全问题,需要做互斥操作,使用作用域互斥锁即可
class SingletonLazyThreadSafe {
private:
static SingletonLazyThreadSafe* instance;
static std::mutex mutex;
SingletonLazyThreadSafe() {} // 私有构造函数
public:
static SingletonLazyThreadSafe* getInstance() {
std::lock_guard<std::mutex> lock(mutex);
if (!instance) {
instance = new SingletonLazyThreadSafe;
}
return instance;
}
};
变体
这种方式非常简洁,并且是线程安全的
c
#include <iostream>
class SingletonLazy
{
private:
SingletonLazy() {} // 私有构造函数
public:
static SingletonLazy* getInstance()
{
static SingletonLazy instance;
return instance;
}
};
SingletonLazy* SingletonLazy::instance = nullptr;
int main()
{
SingletonLazy* instance1 = SingletonLazy::getInstance();
SingletonLazy* instance2 = SingletonLazy::getInstance();
std::cout << (instance1 == instance2) << std::endl; // 输出 1,两个指针变量的内容相同
return 0;
}