标签:单例模式 多线程 rgb 代码 div strong new amp code
保证一个类仅有一个实例,并提供一个该实例的全局访问点。
(1)第一版:
1 class Singleton 2 { 3 public: 4 static Singleton * GetInstance() 5 { 6 if (_instance == nullptr) 7 { 8 _instance = new Singleton(); 9 } 10 return _instance; 11 } 12 private: 13 Singleton(){}//构造为私有,外部不能用 14 Singleton(const Singleton &clone){} //拷?构造 15 Singleton& operator=(const Singleton&) {} 16 static Singleton * _instance; 17 } 18 Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
如上代码在单线程环境使用没有问题,但是存在2个潜在的问题:
1)多线程时,并不安区,例如有2个线程A和B,当2个线程同时第一次走到第6行if (_instance == nullptr) 时,此时2个线程都发现_instance为空,然后 就导致这句_instance = new Singleton()被执行2次,申请了2次内存。
2)_instance 在堆中申请的内存没有被释放。
(2)第二版:线程安区版本,但锁的代价过高
1 class Singleton 2 { 3 public: 4 static Singleton * GetInstance() 5 { 6 std::lock_guard<std::mutex> lock(_mutex); 7 if (_instance == nullptr) 8 { 9 _instance = new Singleton(); 10 atexit(Destructor); 11 } 12 return _instance; 13 } 14 ~Singleton() 15 { 16 } 17 private: 18 static void Destructor() 19 { 20 if (nullptr != _instance) 21 { 22 delete _instance; 23 _instance = nullptr; 24 } 25 } 26 Singleton();//构造 27 Singleton(const Singleton &cpy); //拷?构造 28 Singleton& operator=(const Singleton&) {} 29 static Singleton * _instance; 30 static std::mutex _mutex; 31 } 32 Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
如上代码解决了_instance 在堆中申请的内存没有被释放的问题。
也加了锁,解决了多线程安区问题,这种代码在低并发量的环境下使用没有问题,但是在高并发的环境中不适合,
解释:当_instance已经被创建出来了,此时有A和B....多个线程去访问,当A走到第6行,拿到了锁,此时其它线程走到第6行的话,就会因为拿不到锁而被阻塞。
当多个线程只是去读某个变量时,就没必要加锁 。当多个线程同时改变变量也有读取变量时,才要加锁。
(3)第三版:双检查锁,但是由于内存读写reorder不安区
标签:单例模式 多线程 rgb 代码 div strong new amp code
原文地址:https://www.cnblogs.com/zwj-199306231519/p/14354598.html