转 一种线程安全的单例模式

来源:互联网 发布:mac rar暴力破解 编辑:程序博客网 时间:2024/06/05 08:28

一种线程安全的单例模式

 

 

#include <memory>

// 同步对象
class Mutex
{
public:
    Mutex()
    {
        cout << "initial mutex" << endl;
    }
    ~Mutex()
    {
        cout << "uninitial mutex" << endl;
    }
    void lock()
    {
        cout << "lock" << endl;

 }
    void unlock()
    {
        cout << "unlock" << endl;
    }
};

 

// 同步资源管理对象
class Guard
{
public:
    Guard(Mutex& mtx):
      m_mtx(mtx)
    {
        m_mtx.lock();
    }

      ~Guard()

      {
        m_mtx.unlock();
    }

private:
    Mutex   &m_mtx;
};

// 辅助类; 针对每一个会使用的类型都提供一个锁, 这个锁在进入main之前由主线程创建,
// 最后也由主线程销毁; 创建和销毁绝无线程竞争
template<typename T>
struct SingletonHelper
{
    static Mutex   cs_mtx;
};
template<typename T>
Mutex SingletonHelper<T>::cs_mtx;

// 针对每一个类提供一个单例访问点; 如果从不访问, 则不会创建多余对象
template<typename T>
T& getInstance()
{
    // 智能指针, 保证能够在程序退出时销毁对象, 确保释放跨进程资源
    // 由主线程销毁, 绝对安全
    // 创建对象时因为可能是多线程同时访问getInstance造成, 所以存在竞争, 由后面的代码解决
    static std::auto_ptr<T>  ls_object;
    // 后期getInstance调用ls_object.get()非空, 最初可能为空
    if (ls_object.get() == NULL)
    {
        // 由于这个锁, 进入这里的多线程会被限制为轮流进入
        Guard grd(SingletonHelper<T>::cs_mtx);
        // 第一进入的线程负责创建对象, 后来的线程直接判断为非空
        if (ls_object.get() == NULL)
        {
            // 第一批调用getInstance的线程中, 只有一个能执行这行代码
            ls_object.reset(T::createInstance());
        }
    }
    return *ls_object;
}

class Singleton
{
public:
    // 公开方法
    void method1()
    {
        cout << "method1 call" << endl;
    }

    // 为了getInstance能析构
    // 因为所有的构造函数已被私有, 所以只要不delete &getInstance();就安全
    ~Singleton()
    {
        cout << "last destruct" << endl;
    }

private:
    // 避免多余的创建
    Singleton(int p1, const char *p2)
    {
        cout << "first construct" << endl;
    }
    // 禁止拷贝
    Singleton& operator = (const Singleton&);
    Singleton(const Singleton&);

    // 提供给getInstance获取对象
    static Singleton* createInstance()
    {
        return new Singleton('p1', "p2");
    }
    // 对getInstance放开权限
    friend Singleton& getInstance<Singleton>();
};

template<int iIndex>
class Customer
{
public:
    Customer(int i, const Singleton&)
    {
        cout << "customer " << iIndex << '-' << i << " visit" << endl;
    }
};
// 全局对象的访问
Customer<0> g_cstm(1, getInstance<Singleton>());

int main()
{
    // 全部对象的访问
    Customer<1> cstm2(1, getInstance<Singleton>());
    getInstance<Singleton>().method1();
    Customer<1> cstm3(2, getInstance<Singleton>());

 

 

//未测试