您的位置:首页 > 其它

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

2010-09-20 15:57 281 查看
一种线程安全的单例模式

#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>());
}

//未测试
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: