在开发过程中经常会遇到单例模式,该模式是工作中最常见的设计模式,简单易用是它的特点。单例一般是通过刚开始就申请内存或者用时申请内存的方式实现,用时动态申请内存的话需要加锁,现在主流的也是双重检测加锁的方式。但是今天要讲的是无锁的方式来完成线程安全的实现。
该方法主要使用的是CAS的原理,std::atomic就是cas的原子操作类,代码中使用compare_exchange_strong进行更新单例,如果失败会把pCurNode(期待值)改为最新值,如果成功,就是把pNewNode设置进去。为什么不用compare_exchange_weak呢,因为可能为有概率失败,在没有循环的时候,使用compare_exchange_strong比较好,如果在循环中则用compare_exchange_weak比较好。
代码原创:
#include <atomic> template<class _Ty> class CSingleton { public: static _Ty* GetInstance(); protected: CSingleton() {} CSingleton(const CSingleton& that){} CSingleton& operator=(const CSingleton& that) { return *this; } ~CSingleton() {} }; template<class _Ty> _Ty* CSingleton<_Ty>::GetInstance() { static std::atomic<_Ty*> _atmInstance; _Ty* pCurNode = _atmInstance.load(); if (pCurNode == NULL) { _Ty* pNewNode = new _Ty; _atmInstance.compare_exchange_strong(pCurNode, pNewNode); if (pCurNode != NULL) { //说明其他线程已经更新了 delete pNewNode; } else { pCurNode = pNewNode; } } return pCurNode; }
使用模板方式,这样其他类可以通过继承来实现单例,而不用每次自己都要写一遍。下面是用法代码。
class A :public CSingleton<A> { public: void Pint() { printf("A is Instance.\n"); } };