c++单例模式
单例模式的意图:一个类只能有一个实例。
//单例模式:
懒汉模式:在需要时才创建。需要考虑线程安全。
饿汉模式:系统一运行就构造初始化,不需要考虑线程安全。
//以下是懒汉模式:
//非线程安全版本
1 class Singleton{ 2 private: 3 Singleton(); 4 Singleton(const Singleton &); 5 public: 6 static Singleton* init; 7 static Singleton* getSingleton(); 8 }; 9 Singleton* Singleton::init = nullptr; 10 Singleton * Singleton::getSingleton() { 11 if(init == nullptr){ 12 init = new Singleton(); 13 } 14 return init; 15 }
//线程安全版本,但是加锁的代价过高
//多个线程读的时候其实不需要锁,面对高并发的情况,这个锁的代价比较高
1 class Singleton { 2 private: 3 Singleton(); 4 5 Singleton(const Singleton &); 6 7 ~Singleton(); 8 9 const Singleton &operator=(const Singleton &other); 10 11 public: 12 static mutex m_mutex; 13 static Singleton *m_instance; 14 15 static Singleton *getSingleton(); 16 }; 17 18 mutex Singleton::m_mutex; 19 Singleton *Singleton::m_instance = nullptr; 20 21 Singleton *Singleton::getSingleton() { 22 unique_lock<mutex> lock1(m_mutex); 23 if (m_instance == nullptr) { 24 m_instance = new Singleton(); 25 } 26 return m_instance; 27 }
//双检查锁,但是由于内存读写reorder不安全。
//锁后检查避免多次实例,锁前检查防止两个线程都进了16行之后17行之前,lock等待了之后又实例化。
第19行,执行的顺序是:1.先分配内存,2.调用构造器 3.把这片内存地址值返回给init;
但是由于线程在指令层次抢时间片;那么实际的执行指令顺序未必和上述相同。
1 class Singleton{ 2 private: 3 Singleton(); 4 Singleton(const Singleton &); 5 ~Singleton(); 6 const Singleton & operator=(const Singleton & other); 7 public: 8 static mutex m_mutex; 9 static Singleton* m_instance; 10 static Singleton* getSingleton(); 11 }; 12 13 mutex Singleton::m_mutex; 14 Singleton* Singleton::m_instance = nullptr; 15 Singleton * Singleton::getSingleton() { 16 if(m_instance== nullptr){ 17 unique_lock<mutex> lock1(m_mutex); 18 if(m_instance == nullptr){ 19 m_instance = new Singleton(); 20 } 21 } 22 return m_instance; 23 }
//c++11版本之后的跨平台实现
1 class Singleton { 2 private: 3 Singleton(); 4 5 Singleton(const Singleton &); 6 7 ~Singleton(); 8 9 const Singleton &operator=(const Singleton &other); 10 11 public: 12 static mutex m_mutex; 13 static Singleton *m_instance; 14 15 static Singleton *getSingleton(); 16 }; 17 18 mutex Singleton::m_mutex; 19 Singleton *Singleton::m_instance = nullptr; 20 21 Singleton *Singleton::getSingleton() { 22 if (m_instance == nullptr) { 23 unique_lock<mutex> lock1(m_mutex); 24 if (m_instance == nullptr) { 25 Singleton * temp = static_cast<Singleton*>(operator new(sizeof(Singleton))); 26 new(temp)Singleton();//temp指针上调用Singleton的构造函数 27 m_instance = temp; 28 } 29 } 30 return m_instance; 31 }
//饿汉模式
系统一运行就有一个实例化的对象。
1 class Singleton { 2 private: 3 Singleton(); 4 Singleton(const Singleton &); 5 ~Singleton(); 6 const Singleton &operator=(const Singleton &other); 7 static Singleton *m_instance; 8 public: 9 static Singleton*getS(); 10 }; 11 Singleton *Singleton::m_instance = new Singleton(); 12 Singleton *Singleton::getS() { 13 return m_instance; 14 }