這種實現方法,優勢是實現簡單,缺點是在多線程頻繁訪問下效率比較低,常常出現鎖競爭。適應於不須要頻繁訪問實例的狀況下。多線程
class Singleton { public: static Singleton* GetInstance() { AutoLock lock(mutex); if (!m_instance) m_instance = new Singleton; return m_instance; } private: Singleton(){}; Singleton(const Singleton &); Singleton & operator =(const Singleton &); static Singleton *m_instance; static Mutex m_mutex; }
這種實現方法相對與第一種效率要高,只要未實例化的狀況下進行加鎖,可是代碼看起來不夠簡潔,須要兩次檢查實例指針是否爲空。適用於須要頻繁獲取實例的狀況下。函數
class Singleton { public: static Singleton* GetInstance() { if (!m_instance) { AutoLock lock(mutex); if (!m_instance) m_instance = new Singleton; } return m_instance; } private: Singleton(){}; Singleton(const Singleton &); Singleton & operator =(const Singleton &); static Singleton *m_instance; static Mutex m_mutex; } Mutex Singleton::m_mutex; Singleton* Singleton::m_instance = NULL;
這種實現方法,相對於前面兩種都要簡單,缺點是程序一啓動便在堆上分配實例,無論有沒有客戶調用。適用於程序中肯定確定會使用到該實例的狀況。spa
class Singleton { public: static Singleton* GetInstance() { return m_instance; } private: Singleton(){}; Singleton(const Singleton &); Singleton & operator = (const Singleton &); static Singleton *m_instance; static Mutex m_mutex; } Mutex Singleton::m_mutex; Singleton* Singleton::m_instance = new Singleton;
按陳碩提出的使用Linux下phtread_once線程函數實現,該線程函數的回調在程序的生命週期只會執行一次,利用該線程函數的回調實現初始化,比上面提到的任何一種方法都要高效,並且代碼簡潔。缺點是不能跨平臺。線程
class Singleton { public: static Singleton* GetInstance() { phtread_once(&ponce, &Singleton::Init); return m_instance; } private: void Singleton():m_instance(NULL){}; static void Init() { m_instance = new Singleton; } static Singleton *m_instance; static pthread_once_t ponce; } Singleton* Singleton::m_instance = NULL; pthread_once_t Singleton::ponce;