#pragma once #include <iostream> using namespace std; class Singleton { private: Singleton() { cout << "construct" << endl; } Singleton(Singleton& s) = delete; // 拷贝构造函数禁用 Singleton& operator=(const Singleton&) = delete; // 拷贝赋值运算符禁用 static Singleton* singleton_ptr; public: ~Singleton() { if (singleton_ptr != nullptr) delete singleton_ptr; cout << "desconstruct" << endl; } static Singleton* get_instance() { if (singleton_ptr == nullptr) // (1)注意这里不是线程安全的,当两个线程同时判断时,会进行两次实例化 singleton_ptr = new Singleton; return singleton_ptr; } }; Singleton* Singleton::singleton_ptr = nullptr; int main() { Singleton* ptr1 = Singleton::get_instance(); Singleton* ptr2 = Singleton::get_instance(); }
上边代码有两个问题:
#pragma once #include <iostream> #include <memory> #include <mutex> using namespace std; class Singleton { private: Singleton() { cout << "construct" << endl; } Singleton(Singleton& s) = delete; // 拷贝构造函数禁用 Singleton& operator=(const Singleton&) = delete; // 拷贝赋值运算符禁用 static shared_ptr<Singleton> singleton_ptr; // 这里指针用智能指针 static mutex mu; public: ~Singleton() { cout << "desconstruct" << endl; } static shared_ptr<Singleton> get_instance() { if (singleton_ptr == nullptr) // 两个if语句,双检锁。只有当指针为空的时候才上锁,毕竟锁的消耗还是挺大的 { lock_guard<mutex> lck(mu); // lock_guard 在构造函数里开锁,在析构函数里解锁 if (singleton_ptr == nullptr) // 注意这里不是线程安全的,当两个线程同时判断时,会进行两次实例化 singleton_ptr = shared_ptr<Singleton>(new Singleton); } return singleton_ptr; } }; shared_ptr<Singleton> Singleton::singleton_ptr = nullptr; mutex Singleton::mu; int main() { shared_ptr<Singleton> ptr1 = Singleton::get_instance(); shared_ptr<Singleton> ptr2 = Singleton::get_instance(); return 0; }
原文:https://www.cnblogs.com/qiang-wei/p/12445694.html