1. 餓漢模式
#include<iostream> class singleton { private: static singleton* p; singleton(){} public: static singleton* getInstance() { return p; } }; singleton* singleton::p = new singleton(); int main() { singleton* p = singleton::getInstance(); singleton* p2= singleton::getInstance(); std::cout << p << std::endl; std::cout << p << std::endl; }
這是一個線程安全的實現方法,因為singleton::p在進入main函數之前就由單線程方式實例化,這也就是餓漢模式。相比之下懶漢模式就是第一次使用到類實例的時候才創建。
2. 懶漢模式
class singleton { private: static singleton* p; singleton(){} public: static singleton* getInstance() { if(p == NULL) { p = new singleton(); std::cout << "once" << std::endl; } else std::cout << "not once" << std::endl; return p; } }; singleton* singleton::p = NULL;
3. 懶漢的線程安全問題
在多線程中,可能有多個線程同時判斷p==NULL為真,所以需要加鎖。
class singleton { private: static singleton* p; static pthread_mutex_t mutex; singleton(){} public: static singleton* getInstance() { pthread_mutex_lock(&mutex); if(p == NULL) { p = new singleton(); } pthread_mutex_unlock(&mutex); return p; } }; pthread_mutex_t singleton::mutex = PTHREAD_MUTEX_INITIALIZER; singleton* singleton::p = NULL;
因為加鎖是一個耗時的操作,其實只有在第一次創建實例的時候需要加鎖,所以可以做一個優化:
class singleton { private: static singleton* p; static pthread_mutex_t mutex; singleton(){} public: static singleton* getInstance() { if(p == NULL) { pthread_mutex_lock(&mutex); if(p == NULL) { p = new singleton(); } pthread_mutex_unlock(&mutex); } return p; } }; pthread_mutex_t singleton::mutex = PTHREAD_MUTEX_INITIALIZER; singleton* singleton::p = NULL;
參考鏈接:https://blog.csdn.net/hj605635529/article/details/70172842