剑指Offer面试题:1.实现单例模式
一 题目:实现单例模式Singleton
题目:设计一个类,我们只能生产该类的一个实例。
只能生成一个实例的类是实现了Singleton(单例)模式的类型。由于设计模式在面向对象程序设计中起着举足轻重的作用,在面试过程中很多公司都喜欢问一些与设计模式相关的问题。在常用的模式中,Singleton是唯一一个能够用短短几十行代码完整实现的模式。因此,写一个Singleton的类型是一个很常见的面试题。
二:单例模式的几种实现方法
(1)单线程单例模式
// 单例模式 class Singleton { private: Singleton(){} ~Singleton(){delete m_pSingleton;}; public: static Singleton* Instance(); private: static Singleton*m_pSingleton; }; Singleton* Singleton::m_pSingleton = NULL; Singleton* Singleton::Instance() { if (!m_pSingleton) { m_pSingleton = new Singleton(); } return m_pSingleton; }
这是一个很棒的实现,简单易懂。但这是一个完美的实现吗?不!该方法是线程不安全的,考虑两个线程同时首次调用instance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误!同时,这也不是单例的唯一实现!
(2)懒汉单例模式
a. 使用互斥对象实现懒汉模式
// 单例模式 class Singleton { private: Singleton(){}; ~Singleton(){ delete m_pSingleton; DeleteCriticalSection(&cs);} public: static Singleton * Instance(); private: static Singleton *m_pSingleton; static CRITICAL_SECTION cs; static bool bInitCriticalSection; }; CRITICAL_SECTION Singleton::cs = {0}; bool Singleton::bInitCriticalSection = false; Singleton * Singleton::m_pSingleton = NULL; Singleton * Singleton::Instance() { if (!bInitCriticalSection) { InitializeCriticalSection(&cs); bInitCriticalSection = true; } if (!m_pSingleton) { EnterCriticalSection(&cs); m_pSingleton = new Singleton(); LeaveCriticalSection(&cs); } return m_pSingleton; }
b. 使用内部静态变量实现懒汉模式
此方法也很容易实现,在instance函数里定义一个静态的实例,也可以保证拥有唯一实例,在返回时只需要返回其指针就可以了。推荐这种实现方法,真得非常简单
// 单例模式 class Singleton { private: Singleton(){} ~Singleton(){DeleteCriticalSection(&cs);} public: static Singleton * Instance(); private: static CRITICAL_SECTION cs; static bool bInitCriticalSection; }; CRITICAL_SECTION Singleton::cs = {0}; bool Singleton::bInitCriticalSection = false; Singleton * Singleton::Instance() { if (!bInitCriticalSection) { InitializeCriticalSection(&cs); bInitCriticalSection = false; } EnterCriticalSection(&cs); static Singleton m_Singleton; LeaveCriticalSection(&cs); return &m_Singleton; }
(3)饿汉单例模式
饿汉实现本来就是线程安全的,不用加锁。为啥?自己想!
// 单例模式 class Singleton { private: Singleton(){}; ~Singleton(){} public: static Singleton * Instance(); private: static Singleton *m_pSingleton; }; Singleton * Singleton::m_pSingleton = new Singleton(); Singleton * Singleton::Instance() { return m_pSingleton; }