剑指offer 面试题2:实现Singleton模式
转自:https://blog.csdn.net/liang19890820/article/details/61615495
Singleton 的头文件(懒汉式/饿汉式公用):
// singleton.h #ifndef SINGLETON_H #define SINGLETON_H #include <iostream> #include <mutex> using namespace std; // 单例 - 懒汉式/饿汉式公用 class Singleton { public: static Singleton* GetInstance(); static void DestoryInstance()//手动释放资源 { if (m_pSingleton != NULL) { delete m_pSingleton; m_pSingleton = NULL; } } private: Singleton() {} // 构造函数(被保护) private: static Singleton *m_pSingleton; // 指向单例对象的指针 static mutex m_mutex; // 锁 }; #endif // SINGLETON_H
懒汉式
懒汉式的特点:
- Lazy 初始化
- 非多线程安全
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁(在“线程安全”部分分享如何加锁)才能保证单例,但加锁会影响效率。
在懒汉式下,如果使用多线程,会出现线程安全隐患。为了解决这个问题,可以引入双检锁 - DCL 机制。
// singleton.cpp #include "singleton.h" // 单例 - 懒汉式(双检锁 DCL 机制) Singleton *Singleton::m_pSingleton = NULL; mutex Singleton::m_mutex; Singleton *Singleton::GetInstance() { if (m_pSingleton == NULL) { std::lock_guard<std::mutex> lock(m_mutex); // 自解锁 if (m_pSingleton == NULL) { m_pSingleton = new Singleton(); } } return m_pSingleton; }
饿汉式
饿汉式的特点:
- 非 Lazy 初始化
- 多线程安全
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
// singleton.cpp #include "singleton.h" // 单例 - 饿汉式 Singleton *Singleton::m_pSingleton = new Singleton(); Singleton *Singleton::GetInstance() { return m_pSingleton; }
面试比较好的解法:
// singleton.h #ifndef SINGLETON_H #define SINGLETON_H #include <iostream> using namespace std; // 单例 - 自动释放 class Singleton { public: static Singleton* GetInstance(); private: Singleton() {} // 构造函数(被保护) private: static Singleton *m_pSingleton; // 指向单例对象的指针 // GC 机制 class GC { public: ~GC() { // 可以在这里销毁所有的资源,例如:db 连接、文件句柄等 if (m_pSingleton != NULL) { cout << "Here destroy the m_pSingleton..." << endl; delete m_pSingleton; m_pSingleton = NULL; } } static GC gc; // 用于释放单例 }; }; #endif // SINGLETON_H
// main.cpp #include "singleton.h" Singleton::GC Singleton::GC::gc; // 重要 int main() { Singleton *pSingleton1 = Singleton::GetInstance(); Singleton *pSingleton2 = Singleton::GetInstance(); cout << (pSingleton1 == pSingleton2) << endl; return 0; }