本文最后更新于:2021年4月19日 晚上
概览:单例模式的两种基本实现,保证线程安全!
单例模式
https://blog.csdn.net/Miss_Monster/article/details/88086933
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
饿汉模式
程序启动的时候就会创建一个唯一的实例对象
- 优点:简单
- 缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Singleton { public: static Singleton* GetInstance() { return &m_instance; } private: Singleton(){};
Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton m_instance; class CGarbo{ public: ~CGarbo(){ if(Singleton::m_instance) delete Singleton::m_instance; } }; };
Singleton Singleton::m_instance;
|
- 类CGarbo被定义为Singleton的私有内嵌类,以防该类被在其他地方滥用。
- 程序运行结束时,系统会调用CSingleton的静态成员Garbo的析构函数,该析构函数会删除单例的唯一实例。
如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。
懒汉模式
等到使用的时候程序再常见实例对象!
- 优点:第一次使用实例对象时,创建对象,进程启动无负载,多个单例实例启动顺序可自由控制!
- 缺点:复杂!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| class Singleton { public: static Singleton* GetInstance() { if (nullptr == m_pInstance) { m_mtx.lock(); if (nullptr == m_pInstance) { m_pInstance = new Singleton(); } m_mtx.unlock(); } return m_pInstance; } class CGarbo { public: ~CGarbo(){ if (Singleton::m_pInstance) delete Singleton::m_pInstance; } }; static CGarbo Garbo; private: Singleton(){}; Singleton(Singleton const&); Singleton& operator=(Singleton const&); static Singleton* m_pInstance; static mutex m_mtx; };
Singleton* Singleton::m_pInstance = nullptr; Singleton::CGarbo Garbo; mutex Singleton::m_mtx;
void func(int n) { cout << Singleton::GetInstance() << endl; }
int main() { thread t1(func, 10); thread t2(func, 10); t1.join(); t2.join(); cout << Singleton::GetInstance() << endl; cout << Singleton::GetInstance() << endl; }
输出结果: 4个相同的地址!
|
其他
2021/04/17 蓝信移动面试
二面中一不小心被面试官问到了懒汉模式,延迟加载的实现,他问我解决并发问题的方法?
支支吾吾好久之后,面试官给我讲了check - lock - check
的方法。
思想和上面的方法类似,先检测,然后加锁,获得锁之后再次进行检测,如果检测到已经被实例化,直接返回即可!