咱們都很清楚一個簡單的單例模式該怎樣去實現:構造函數聲明爲private或protect防止被外部函數實例化,內部保存一個private static的類指針保存惟一的實例,實例的動做由一個public的類方法代勞,該方法也返回單例類惟一的實例。面試
上代碼: 安全
class singleton { protected: singleton(){} private: static singleton* p; public: static singleton* instance(); }; singleton* singleton::p = NULL; singleton* singleton::instance() { if (p == NULL) p = new singleton(); return p; }
這是一個很棒的實現,簡單易懂。但這是一個完美的實現嗎?不!該方法是線程不安全的,考慮兩個線程同時首次調用instance方法且同時檢測到p是NULL值,則兩個線程會同時構造一個實例給p,這是嚴重的錯誤!同時,這也不是單例的惟一實現!函數
單例大約有兩種實現方法:懶漢與餓漢。性能
特色與選擇:spa
線程不安全,怎麼辦呢?最直觀的方法:加鎖。線程
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } private: static singleton* p; public: static pthread_mutex_t mutex; static singleton* initance(); }; pthread_mutex_t singleton::mutex; singleton* singleton::p = NULL; singleton* singleton::initance() { if (p == NULL) { pthread_mutex_lock(&mutex); if (p == NULL) p = new singleton(); pthread_mutex_unlock(&mutex); } return p; }
此方法也很容易實現,在instance函數裏定義一個靜態的實例,也能夠保證擁有惟一實例,在返回時只須要返回其指針就能夠了。推薦這種實現方法,真得很是簡單。 指針
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } public: static pthread_mutex_t mutex; static singleton* initance(); int a; }; pthread_mutex_t singleton::mutex; singleton* singleton::initance() { pthread_mutex_lock(&mutex); static singleton obj; pthread_mutex_unlock(&mutex); return &obj; }
爲何我不講「線程安全的餓漢實現」?由於餓漢實現原本就是線程安全的,不用加鎖。爲啥?本身想!code
class singleton { protected: singleton() {} private: static singleton* p; public: static singleton* initance(); }; singleton* singleton::p = new singleton; singleton* singleton::initance() { return p; }
是否是特別簡單呢?blog
以空間換時間,你說簡單不簡單?同步
面試的時候,線程安全的單例模式怎麼寫?確定怎麼簡單怎麼寫呀!餓漢模式反而最懶[正經臉]!