分享一个线程安全的单例模板类

单例模式应该说是最简单的设计模式了。在此分享一个线程安全的单例模板类。

template <typename Type>

class CSingleton

{

public:

static Type* GetInstance()

{

// kBeingCreatedMarker用来表示单例实例正在创建过程中。

// 此处初始化为1是因为操作系统不会分配地址为1的指针。

static const volatile intptr_t kBeingCreatedMarker = 1;

// 如果m_pInstance不为空且不是正在创建,则返回m_pInstance

if (m_pInstance != NULL && m_pInstance != kBeingCreatedMarker)  {

return reinterpret_cast<Type*>(m_pInstance);

}

// 使用InterlockedCompareExchange函数保证原子操作

// 函数判断m_pInstance是否等于NULL,如果是则将m_pInstance赋值为kBeingCreatedMarker

// 函数返回值为m_pInstance的初始值,通过判断返回值是否等于NULL得知是否可以进行实例化

if (InterlockedCompareExchange(

reinterpret_cast<volatile LONG*>(&m_pInstance),

static_cast<LONG>(kBeingCreatedMarker),

static_cast<LONG>(NULL)) == NULL)  {

static Type newval;

m_pInstance = reinterpret_cast<intptr_t>(&newval);

return &newval;

}

// 如果m_pInstance是kBeingCreatedMarker,即表示正在创建中

// SwitchToThread让出剩余的时间片等待创建过程完成

while (m_pInstance == kBeingCreatedMarker)

{

SwitchToThread();

}

// 到达此处表明创建过程已经完成了

return reinterpret_cast<Type*>(m_pInstance);

}

Type& operator*()

{

return *GetInstance();

}

Type* operator->()

{

return GetInstance();

}

private:

static volatile intptr_t m_pInstance;

};

template <typename Type>

volatile intptr_t CSingleton<Type>::m_pInstance = NULL;

假设我们有个CCmdManager类

class CCmdManager

{

public:

CCmdManager()

{

std::cout << "Hello, I am the only one!";

};

};

使用方法很简单,如下:

int main()

{

CCmdManager *pMgr = CSingleton<CCmdManager>::GetInstance();

CCmdManager &mgr = *(CSingleton<CCmdManager>::GetInstance());

}

如果我们想要完全限制CCmdManager不被实例化第二次,我们可以这么做

class CCmdManager

{

private:

CCmdManager()

{

std::cout << "Hello, I am the only one!";

};

friend class CSingleton<CCmdManager>;

};

通过将构造函数设置为private,且仅对class CSingleton<CCmdManager>开放,就可以保证用户只能使用CCmdManager *pMgr = CSingleton<CCmdManager>::GetInstance()这种方式调用了。

顺便说一下,这个代码的一些局限性

1. 因为使用了InterlockedCompareExchange这个函数,所以只能在Windows下使用,但是不可否定的是这个函数的效率极高,完成比较并交换只要一条指令。

2. CSingleton在实例化对象时,只支持默认构造函数。一般情况下,这个也是可以接受的。

时间: 2024-08-03 09:56:16

分享一个线程安全的单例模板类的相关文章

C++实现一个线程安全的单例工厂

我们见到经常有人用 static 局部对象的方式实现了类似单例模式,最近发现一篇文章明确写明 编译器在处理  static局部变量的时候 并不是线程安全的 !!! http://blogs.msdn.com/b/oldnewthing/archive/2004/03/08/85901.aspx 于是实现了一个单例工厂  并且是线程安全的 #ifndef SINGLETONFACTORY_H #define SINGLETONFACTORY_H #include "windows.h"

设计一个线程安全的单例(Singleton)模式

在设计单例模式的时候,虽然很容易设计出符合单例模式原则的类类型,但是考虑到垃圾回收机制以及线程安全性,需要我们思考的更多.有些设计虽然可以勉强满足项目要求,但是在进行多线程设计的时候.不考虑线程安全性,必然会给我们的程序设计带来隐患.此处,我们不介绍什么是单例模式,也不介绍如何设计简单的设计模式,因为你完全可以在书上或者在博客中找到.此处我们的目的就是设计一个使用的单例模式类.单例模式需要注意与思考的问题: (1)如何仅能实例化一个对象? (2)怎么样设计垃圾回收机制? (3)如何确保线程安全性

一个基于C++11的单例模板类

1 #ifndef _SINGLETON_H_ 2 #define _SINGLETON_H_ 3 4 #include <mutex> 5 #include <memory> 6 7 template<typename T> 8 class Singleton { 9 public: 10 template <typename... ArgTypes> 11 static T* getInstance(ArgTypes... args) { 12 stat

求教C++单例模板类的问题eZ98

代码如下:编译时出现链接错误:各位大大们来看下这是什么一个情况? http://weibo.com/p20180109p/1001604191068680786935焊破巴EEG13P佑菊等卦 http://weibo.com/p20180109p/1001604188414684566397孔鞠勘QRTdMu床枪可两 http://weibo.com/p20180109p/1001604184711873335681搪斜镁UYIT9g环亩优僬 http://weibo.com/p2018010

C++可继承的单例基类模板

目录 一.介绍 二.代码 三.关键处 四.使用限制 五.参考资料 一.介绍 最近在写一个项目,其中用到好几个单例,类本身的设计不是很复杂,但是如果每个都写一遍单例又觉得有点冗余:所以查资料写了一个单例基类模板,只要一个类继承这个基类并且以自身作为模板参数就可以实现一个单例:关于单例本身的介绍在这里不重点介绍. 特点: RAII,使用 std::shared_ptr来管理资源 线程安全,加了锁 以上特性基于C++11 二.代码 // bridf: a singleton base class of

Singleton 单例模板

1 // singleton.h 2 3 #ifndef SINGLETON_H 4 #define SINGLETON_H 5 6 // 单例基类模板 7 template <class T> 8 class Singleton 9 { 10 public: 11 static T& give_me() 12 { 13 static T s_inst; 14 return s_inst; 15 } 16 17 private: 18 // 禁止实现拷贝构造与拷贝赋值函数 19 exp

C++ 单链表模板类实现

单链表的C语言描述 基本运算的算法--置空表.求表的长度.取结点.定位运算.插入运算.删除运算.建立不带头结点的单链表(头插入法建表).建立带头结点的单链表(尾插入法建表),输出带头结点的单链表 #include<cstdio>#include<iostream>using namespace std;template <class T>class Linklist{private: struct node { T date; node * next; node():n

从一个简单的Java单例示例谈谈并发

一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static UnsafeLazyInitiallization instance; private UnsafeLazyInitiallization() { } public static UnsafeLazyInitiallization getInstance(){ if(instance==null){ /

从一个简单的Java单例示例谈谈并发 JMM JUC

原文: http://www.open-open.com/lib/view/open1462871898428.html 一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static UnsafeLazyInitiallization instance; private UnsafeLazyInitiallization() { } public static U