C++实现线程安全单例类(可运行)
心血来潮手撕一下线程安全的单例类,做项目的时候写过单例,今天自己动手写发现之前写的并不对。下面参考了小林 coding 的代码,针对加锁的懒汉模式,自己加了一个 AutoRelease 的内部类,可以自动释放单例类的实例资源。
加锁-懒汉模式
懒汉模式:系统运行中实例并不存在,只有当需要使用该实例时,才会去创建并使用实例。
#include <iostream> #include <thread> #include <mutex> #include <unistd.h> using namespace std; class Singleton { public: static Singleton* get_instance(); void print(); private: friend class AutoRelease; Singleton(); ~Singleton(); Singleton(const Singleton& signal) = delete; const Singleton& operator=(const Singleton& signal) = delete; private: static Singleton *m_Instance; static std::mutex m_Mutex; private: class AutoRelease { public: AutoRelease() { std::cout << "AutoRelease()" << std::endl; } ~AutoRelease() { std::unique_lock<std::mutex> lock(m_Mutex); if (m_Instance) { delete m_Instance; m_Instance = nullptr; } std::cout << "~AutoRelease()" << std::endl; } }; private: static AutoRelease m_At; }; Singleton *Singleton::m_Instance = nullptr; std::mutex Singleton::m_Mutex; Singleton::AutoRelease Singleton::m_At; Singleton* Singleton::get_instance() { if (m_Instance == nullptr) { std::unique_lock<std::mutex> lock(m_Mutex); if (m_Instance == nullptr) { m_Instance = new Singleton; } } return m_Instance; } void Singleton::print() { std::cout << "addr: " << this << std::endl; } Singleton::Singleton() { std::cout << "Singleton()" << std::endl; } Singleton::~Singleton() { std::cout << "~Singleton()" << std::endl; } // operator func void test() { Singleton::get_instance()->print(); } int main() { // create three threads thread t1(test); thread t2(test); thread t3(test); // threads joined t1.join(); t2.join(); t3.join(); return 0; }
局部静态变量-懒汉模式(推荐)
在 C++11 内部静态变量是线程安全的,该方法实现的代码量最少。
#include <iostream> #include <thread> #include <mutex> #include <unistd.h> using namespace std; class Singleton { public: static Singleton& get_instance(); void print(); private: Singleton(); ~Singleton(); Singleton(const Singleton& signal) = delete; const Singleton& operator=(const Singleton& signal) = delete; }; Singleton& Singleton::get_instance() { static Singleton singal; // static var return singal; } void Singleton::print() { std::cout << "addr: " << this << std::endl; } Singleton::Singleton() { std::cout << "Singleton()" << std::endl; } Singleton::~Singleton() { std::cout << "~Singleton()" << std::endl; } // operator func void test() { Singleton::get_instance().print(); } int main() { // create three threads thread t1(test); thread t2(test); thread t3(test); // threads joined t1.join(); t2.join(); t3.join(); return 0; }
饿汉模式
饿汉模式:在程序运行时就创建实例,需要使用的话可直接调用,本身就是线程安全的。
#include <iostream> #include <thread> #include <mutex> #include <unistd.h> using namespace std; class Singleton { public: static Singleton* get_instance(); void print(); private: friend class AutoRelease; Singleton(); ~Singleton(); Singleton(const Singleton& signal) = delete; const Singleton& operator=(const Singleton& signal) = delete; private: static Singleton *g_Instance; private: class AutoRelease { public: AutoRelease() { std::cout << "AutoRelease()" << std::endl; } ~AutoRelease() { if (g_Instance) { delete g_Instance; g_Instance = nullptr; } std::cout << "~AutoRelease()" << std::endl; } }; private: static AutoRelease m_At; }; /* create an instance when code runs */ Singleton *Singleton::g_Instance = new Singleton; Singleton::AutoRelease Singleton::m_At; Singleton* Singleton::get_instance() { return g_Instance; } void Singleton::print() { std::cout << "addr: " << this << std::endl; } Singleton::Singleton() { std::cout << "Singleton()" << std::endl; } Singleton::~Singleton() { std::cout << "~Singleton()" << std::endl; } // operator func void test() { Singleton::get_instance()->print(); } int main() { // create three threads thread t1(test); thread t2(test); thread t3(test); // threads joined t1.join(); t2.join(); t3.join(); return 0; }#C++##暑期实习#