C++单例模式(懒汉和饿汉)与线程安全
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
个性签名:时间会解决一切