线程安全单例模式模板类

#ifndef __SINGTON_H__
#define __SINGTON_H__

#include <mutex>
#include <iostream>
#include <atomic> // 解决reorder方案2
using namespace std;

//---------------------------------------------------
template <typename T>
class Sington {
public:
    Sington() = delete;
    Sington(const Sington& s) = delete;
    ~Sington() = delete;

    // 解决reorder方案1
    static T* getInstance() {
        if (m_pInstance == nullptr) {
            lock_guard<mutex> lock(m_mutex);
            if (m_pInstance == nullptr) {
                T* ptmp = new T(); // 网上说:巧妙的解决了编译器reorder代码时,先将地址赋值给m_pInstance后执行构造的问题。但是不知道会不会被编译器优化成m_pInstance = new T()?
                m_pInstance = ptmp;
            }
        }

        return m_pInstance;
    }

    // 解决reorder方案2
    static T* getInstance2() {
        T* tmp = m_pInstance2.load(std::memory_order_relaxed);
        std::atomic_thread_fence(std::memory_order_acquire);
        if (tmp == nullptr) {
            lock_guard<mutex> lock(m_mutex);
            tmp = m_pInstance2.load(std::memory_order_relaxed);
            if (tmp == nullptr) {
                tmp = new T();
                std::atomic_thread_fence(std::memory_order_release);
                m_pInstance2.store(tmp, std::memory_order_relaxed);
            }
        }

        return tmp;
    }

    static void destroy() {
        delete m_pInstance;
    }

    static void destroy2() {
        
    }

private:
    static T* m_pInstance; // 解决reorder方案1
    static atomic<T*> m_pInstance2;
    static mutex m_mutex;
};

template <typename T>
T* Sington<T>::m_pInstance = nullptr;

template <typename T>
atomic<T*> Sington<T>::m_pInstance2;

template <typename T>
mutex Sington<T>::m_mutex;

//---------------------------------------------------
class A {
public:
    A(const A& a) = delete;
    ~A() {
        cout << "A destroy" << endl;
    }

    void print() {
        cout << m_data << " sington A print" << endl;
    }

private:
    A() {}

    int m_data = 0;

    friend class Sington<A>;
};

#endif // !__SINGTON_H__
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值