一种线程安全的单例模式(10.4.1更新)
2009-11-21 16:50
330 查看
旧版本:
我自己使用的版本:
需要boost中的几个组件
上面代码的头文件下载(含有一个简单的测试):
http://download.csdn.net/source/2192413
#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>()); }
我自己使用的版本:
需要boost中的几个组件
#include <boost/shared_ptr.hpp> #include <boost/function.hpp> #include <boost/bind.hpp> #include <windows.h> namespace Scan { typedef unsigned int uint32; /** @brief 类分配器 有特殊用处的类应该特化它 */ template<typename T> struct ClassAllocator { static T* alloc() { return new T; } static void unalloc(T *p) { delete p; } }; /** @brief 资源管理类 保证在析构时调用某函数 */ class ResGuard { public: /** @brief 构造函数 @param p 调用函数的参数; 可以是类指针 @param f 要调用的函数; 可以是类成员函数 */ template<typename T, typename FunType> ResGuard(FunType f, T *p): m_f(boost::bind(f, p)){} ~ResGuard() { m_f(); } private: /** @brief 用boost::function来解耦 */ boost::function<void(void)> m_f; }; class ISyncObject { public: virtual ~ISyncObject() = 0{} virtual bool lock(uint32 waitTime = -1) = 0; virtual void unlock() = 0; }; class SingleLocker { public: SingleLocker(ISyncObject *o): m_guard(&ISyncObject::unlock, o) { o->lock(); } SingleLocker(ISyncObject &o): m_guard(&ISyncObject::unlock, &o) { o.lock(); } private: ResGuard m_guard; }; namespace Windows { /** @brief 临界区对象 同一线程不会在同一对象上递归锁住; 即, 临界区对象对每个线程有计数 */ class CriticalSection: public ISyncObject { public: CriticalSection(); ~CriticalSection(); bool lock(uint32 waitTime = -1); void unlock(); private: CRITICAL_SECTION m_cs; }; CriticalSection::CriticalSection() { InitializeCriticalSection(&m_cs); } CriticalSection::~CriticalSection() { DeleteCriticalSection(&m_cs); } bool CriticalSection::lock(uint32 waitTime/* = -1*/) { EnterCriticalSection(&m_cs); return true; } void CriticalSection::unlock() { LeaveCriticalSection(&m_cs); } } /** @brief 单例模式 使用它有两个步骤: 1. 继承; class T: public Singleton<T>{} 2. 私有化构造函数, 并添加友元; friend struct classAllocator<T>; */ template<typename T, typename MutexType = Windows::CriticalSection> class ISingleton { public: static T& getSingleton() { return *getSingletonPtr(); } static T* getSingletonPtr() { static boost::shared_ptr<T> cs_object; if (cs_object.get() == NULL) { SingleLocker locker(cs_synObject); if (cs_object.get() == NULL) { cs_object = boost::shared_ptr<T>( ClassAllocator<T>::alloc(), &ClassAllocator<T>::unalloc); } } return cs_object.get(); } protected: ~ISingleton(){} private: static MutexType cs_synObject; }; template<typename T, typename MutexType> MutexType ISingleton<T, MutexType>::cs_synObject; }
上面代码的头文件下载(含有一个简单的测试):
http://download.csdn.net/source/2192413
相关文章推荐
- 解决单例设计模式中的懒汉设计模式存在线程安全问题(并且在一定程度上提高效率)的一种解决方法
- 单例模式--一种线程安全的写法
- Lazy方式单列模式,一种线程安全模式的新选择
- 一种线程安全的单例模式实现
- 转 一种线程安全的单例模式
- 一种线程安全的单例模式实现
- C#中不需要用锁的线程安全的Singleton设计模式开发者在线 Builder.com.cn 更新时间:2008-07-19作者: 来源:
- 一种在旧代码上增加新需求的重构模式
- 为其他对象提供一种代理以控制对这个对象的访问-代理模式
- 深入探讨:LBS是一种工具而非一种模式
- 深入探讨:LBS是一种工具而非一种模式
- tensorflow27《TensorFlow实战Google深度学习框架》笔记-10-04 异步更新模式样例程序 code
- 性能改善的一种模式
- 转Javascript的一种模块模式
- 网红经济,会是一种短命模式吗?
- 一种夜间模式简单实现方案
- C++ 线程安全的单例模式
- MVPHelper更新日志 --- 新增常规分包模式
- (源码)关于A->B*->D的时间序列频繁模式挖掘的思考 1.26更新
- 一、Spring单例模式与线程安全