本文最后编辑于 前,其中的内容可能需要更新。
单例是最简单的一种设计模式,其只有一个类定义,整个系统运行中,该类只允许存在一个实例。
单例模式不能让外部创建该类实例,只能自己类内部创建唯一实例,所以需要将构造函数私有化。
单例通常有两种实现方式:饿汉模式和懒汉模式。
恶汉模式:在系统初始化时创建实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Singleton { public: static Singleton* getInstance(); ~Singleton() { delete _instance; } protected: Singleton(); private: static Singleton* _instance; };
Singleton *Singleton::_instance = new Singleton(); Singleton* Singleton::getInstance() { return _instance; }
|
恶汉模式将单例对象设置为静态对象,在程序启动时即可完成对象初始化,所以是线程安全的。
懒汉模式:实例在第一次被调用时创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Singleton { public: static Singleton* getInstance(); ~Singleton() { if( (_instance != NULL) delete _instance; } protected: Singleton(); private: static Singleton* _instance; };
Singleton *Singleton::_instance = NULL; Singleton* Singleton::getInstance() { if( _instance == NULL) { _instance = new Singleton(); } return _instance; }
|
懒汉模式在多线程程序中是非线程安全的,可能会创造多个实例而造成内存泄漏。所以需要加锁。
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
| class Lock { private: mutex& mtex; public: Lock(mutex& m) : mtex(m) { mtex.Lock(); } ~Lock() { mtex.Unlock(); } }; class Singleton { public: static Singleton* getInstance(); ~Singleton() { if( (_instance != NULL) delete _instance; } protected: Singleton(); private: static Singleton* _instance; static mutex m; };
Singleton *Singleton::_instance = NULL; Singleton* Singleton::getInstance() { Lock lock(m); if( _instance == NULL) { _instance = new Singleton(); } return _instance; }
|
但是保证线程安全,其实只需要在第一次调用时加锁,_instance赋值后,每次加锁就成了浪费的开销。所以为了解决这个问题,通常采用双重判断。
1 2 3 4 5 6 7 8 9
| Singleton* Singleton::getInstance() { if( _instance == NULL) { Lock lock(m); if( _instance == NULL) { _instance = new Singleton(); } } return _instance; }
|