定义:
要求一个类只能生成一个对象,所有对象对它的依赖相同。
优点:
- 只有一个实例,减少内存开支。应用在一个经常被访问的对象上
- 减少系统的性能开销,应用启动时,直接产生一单例对象,用永久驻留内存的方式。
- 避免对资源的多重占用
- 可在系统设置全局的访问点,优化和共享资源访问。
缺点:
- 一般没有接口,扩展困难。原因:接口对单例模式没有任何意义;
- 单例模式对测试是不利的。如果单例模式没完成,是不能进行测试的。
- 单例模式与单一职责原则有冲突。原因:一个类应该只实现一个逻辑,而不关心它是否是单例,是不是要单例取决于环境;单例模式把“要单例”和业务逻辑融合在一个类。
使用场景:
- 内存消耗大的
- 硬件
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
//法一:懒汉式单例(线程不安全)
//线程不安全,当几个线程同时执行到语句if (singleton == nullptr)时,singleton都还没有被创建,所以就重复创建了几个实例。
//可以通过在getSingelton中加锁来实现
#if 0
class Singleton
{
private:
static Singleton *singleton;
public:
inline static Singleton *getSingleton()
{
if (singleton == nullptr)
{
singleton = new Singleton();
}
return singleton;
}
};
#endif
//法二:懒汉式单例(线程安全)
//在getSingelton中加锁来实现
//但是这种情况会在调用getSingleton的时候每次都加锁,耽误时间
//可以再if (singleton == nullptr)中加锁
#if 0
std::mutex single_mtx;
class Singleton
{
public:
inline static Singleton* getSingleton()
{
std::unique_lock<std::mutex> single_lock(single_mtx);
if (singleton == nullptr)
{
singleton = new Singleton();
}
return singleton;
}
private:
static Singleton* singleton;
};
#endif
std::mutex single_mtx;
class Singleton
{
public:
inline static Singleton* getSingleton()
{
if (singleton == nullptr)
{
//单独在这加的话会出现多个线程都满足singleton == nullptr,然后进入到这的情况。故需要在下面再次判断一次singleton == nullptr,然后创建对象
std::unique_lock<std::mutex> single_lock(single_mtx);
if (singleton == nullptr)//双重判断保证线程安全
{
singleton = new Singleton();
}
}
return singleton;
}
private:
static Singleton* singleton;
};
Singleton *Singleton::singleton = nullptr;
void printAddr()
{
std::unique_lock<std::mutex> lock(mtx);
Singleton *singleton = Singleton::getSingleton();
std::cout << singleton << std::endl;
}
int main()
{
std::thread threads[5];
for (auto &t : threads)
t = std::thread(printAddr);
for (auto &t : threads)
t.join();
return 0;
}