在开发过程中经常会遇到单例模式,该模式是工作中最常见的设计模式,简单易用是它的特点。单例一般是通过刚开始就申请内存或者用时申请内存的方式实现,用时动态申请内存的话需要加锁,现在主流的也是双重检测加锁的方式。但是今天要讲的是无锁的方式来完成线程安全的实现。

  该方法主要使用的是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"); }
};