单件模式:
有些类只应该存在一个实例。如线程池,缓存,注册表等对象。单件模式能确保一个类只有一个实例,并提供一个全局访问点。
全局变量? 必须在程序刚开始就创建对象,而单件模式可以在需要时才创建对象。
实现:
1.构造函数声明为私有。
2.声明静态实例对象。
3.提供实例的全局访问点,当需要实例时,向类查询,它会返回静态实例对象。查询时可以采用延迟实例化的方式创建单件,这对于资源敏感的对象十分重要。
懒汉式:非线程安全。程序调用时才创建。
饿汉式:线程安全。程序编译时期创建类实例。
多线程操作出现问题:
1.同步getInstance ()方法
需要加锁,但只有第一次执行此方法,才真正需要同步,之后的同步会引起程序效率下降。
2.先创建实例,不再延迟实例化。
当可能不需要实例对象时,提前静态初始化会占用一定的内存。
3.双重检查加锁
在getInstance()中不存在实例时才同步,解决1中同步引起效率下降的问题。
单件类析构:
1 不要直接使用类的析构函数来释放,否则将引起无休止的循环!
2 正确方法:另提供一个释放的接口,由这个单例的使用者来释放。
懒汉式 多线程不安全。
#include <iostream>
#include <mutex>
class Singleton
{
private:
Singleton() {}
static Singleton* uniqueInstance;
public:
static Singleton* getInstance()
{
if (uniqueInstance == nullptr)
{
printf("uniqueInstance=nullptr\n");
uniqueInstance = new Singleton();
}
printf("return uniqueInstance \n");
return uniqueInstance;
}
~Singleton(){}
void destroy()
{
if (uniqueInstance != nullptr)
{
delete uniqueInstance;
uniqueInstance = nullptr;
}
}
};
Singleton* Singleton::uniqueInstance = nullptr;
int main()
{
Singleton* s1, * s2;
thread thread1([&](){s1 = Singleton::getInstance(); });
thread thread2([&]() { s2 = Singleton::getInstance(); });
thread1.join();
thread2.join();
cout << (void*)s1 << endl;
cout << (void*)s2 << endl;
system("pause");
}
地址不同。
安全的懒汉式(3,双重检查加锁):
#include <vector>
#include <unordered_map>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include<thread>
#include <mutex>
mutex m;
class Singleton
{
private:
Singleton() {}
static Singleton* uniqueInstance;
public:
static Singleton* getInstance()
{
if (uniqueInstance == nullptr)
{
m.lock();
if (uniqueInstance == nullptr)
{
printf("uniqueInstance=nullptr\n");
uniqueInstance = new Singleton();
}
m.unlock();
}
printf("return uniqueInstance \n");
return uniqueInstance;
}
~Singleton() {}
void destroy()
{
if (uniqueInstance != nullptr)
{
delete uniqueInstance;
uniqueInstance = nullptr;
}
}
};
Singleton* Singleton::uniqueInstance = nullptr;
int main()
{
Singleton* s1, * s2;
thread thread1([&](){s1 = Singleton::getInstance(); });
thread thread2([&]() { s2 = Singleton::getInstance(); });
thread1.join();
thread2.join();
cout << (void*)s1 << endl;
cout << (void*)s2 << endl;
system("pause");
}
饿汉式,线程安全
class Singleton
{
private:
Singleton() {}
static Singleton* uniqueInstance;
public:
static Singleton* getInstance()
{
return uniqueInstance;
}
~Singleton(){}
void destroy()
{
if (uniqueInstance != nullptr)
{
delete uniqueInstance;
uniqueInstance = nullptr;
}
}
};
Singleton* Singleton::uniqueInstance = new Singleton();