1. 单例模式简介
- 目的: 确保一个类只有一个实例,并提供一个全局访问点。
- 常见用例: 日志记录、配置管理、线程池等。
classDiagram class Singleton { - static Singleton* instance - Singleton() + static Singleton* getInstance() } Singleton <|-- Singleton : 使用实例
2. 饿汉模式(Eager Initialization)
-
描述: 实例在类加载时创建。
-
代码示例:
class Singleton { private: static Singleton* instance; // 私有构造函数以防止外部实例化 Singleton() {} public: // 获取实例的静态方法 static Singleton* getInstance() { return instance; } }; // 在类加载时初始化实例 Singleton* Singleton::instance = new Singleton();
-
优点: 简单且线程安全,不需要额外的同步措施。
-
缺点: 即使实例可能不会被使用,也会在类加载时创建,可能导致不必要的资源消耗。
3. 饱汉模式(Lazy Initialization)
-
描述: 实例仅在需要时才创建。
-
代码示例:
class Singleton { private: static Singleton* instance; // 私有构造函数以防止外部实例化 Singleton() {} public: // 获取实例的静态方法 static Singleton* getInstance() { if (instance == nullptr) { instance = new Singleton(); } return instance; } }; // 将静态成员初始化为nullptr Singleton* Singleton::instance = nullptr;
-
优点: 实例仅在需要时创建,节省资源。
-
缺点: 如果不加同步措施,则在多线程环境下可能不安全。
4. 线程安全的考虑
-
双重检查锁定: 一种使懒汉模式线程安全的技术。
-
带互斥锁的代码示例:
#include <mutex> class Singleton { private: static Singleton* instance; static std::mutex mtx; Singleton() {} public: static Singleton* getInstance() { if (instance == nullptr) { std::lock_guard<std::mutex> lock(mtx); if (instance == nullptr) { instance = new Singleton(); } } return instance; } }; Singleton* Singleton::instance = nullptr; std::mutex Singleton::mtx;
5. 总结与最佳实践
- 方法比较: 何时使用饿汉模式和饱汉模式。
- 避免陷阱: 特别是在多线程环境中,注意内存管理。