博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++模式设计-多线程下的单例模式
阅读量:4971 次
发布时间:2019-06-12

本文共 3151 字,大约阅读时间需要 10 分钟。

1 教科书里的单例模式

我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例。

上代码: 

class singleton{protected:  singleton(){}private:  static singleton* p;public:  static singleton* instance();};singleton* singleton::p = NULL;singleton* singleton::instance(){  if (p == NULL)    p = new singleton();  return p;}

 

这是一个很棒的实现,简单易懂。但这是一个完美的实现吗?不!该方法是线程不安全的,考虑两个线程同时首次调用instance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误!同时,这也不是单例的唯一实现!

 

一、懒汉模式:即第一次调用该类实例的时候才产生一个新的该类实例,并在以后仅返回此实例。

需要用锁,来保证其线程安全性:原因:多个线程可能进入判断是否已经存在实例的if语句,从而non thread safety.

使用double-check来保证thread safety.但是如果处理大量数据时,该锁才成为严重的性能瓶颈。

 1、静态成员实例的懒汉模式:

class Singleton{private:    static Singleton* m_instance;    Singleton(){}public:    static Singleton* getInstance();};Singleton* Singleton::getInstance(){    if(NULL == m_instance)    {        Lock();//借用其它类来实现,如boost        if(NULL == m_instance)        {            m_instance = new Singleton;        }        UnLock();    }    return m_instance;}

2、内部静态实例的懒汉模式

这里需要注意的是,C++0X以后,要求编译器保证内部静态变量的线程安全性,可以不加锁。但C++ 0X以前,仍需要加锁。

class SingletonInside{private:    SingletonInside(){}public:    static SingletonInside* getInstance()    {        Lock(); // not needed after C++0x        static SingletonInside instance;        UnLock(); // not needed after C++0x        return &instance;     }};

 

使用实例:

1 #include
2 using namespace std; 3 class CSingleton 4 { 5 private: 6 CSingleton() { 7 } 8 ~CSingleton() { 9 if (m_pInstance == NULL) {10 return;11 }12 delete m_pInstance;13 m_pInstance = NULL;14 }15 static CSingleton *m_pInstance;16 public:17 static CSingleton * GetInstance() {18 if(m_pInstance == NULL)19 m_pInstance = new CSingleton();20 return m_pInstance;21 }22 };23 CSingleton* CSingleton::m_pInstance = NULL;//类的静态成员变量需要在类外边初始化24 25 26 class SingletonInside27 {28 private:29 SingletonInside(){}30 public:31 static SingletonInside* getInstance()32 {33 static SingletonInside instance;34 return &instance; 35 }36 void init(){37 m_data = 10;38 }39 void set(){40 ++m_data;41 }42 int m_data;43 };44 45 int main() {46 47 SingletonInside* single1 = SingletonInside::getInstance();48 SingletonInside* single2 = SingletonInside::getInstance();49 50 single1->set();51 if (single1 == single2) {52 cout<<"Same"<
init();54 single1->set();55 cout<
m_data <

output:

Same11

二、饿汉模式:即无论是否调用该类的实例,在程序开始时就会产生一个该类的实例,并在以后仅返回此实例。

由静态初始化实例保证其线程安全性,WHY?因为静态实例初始化在程序开始时进入主函数之前就由主线程以单线程方式完成了初始化,不必担心多线程问题。

故在性能需求较高时,应使用这种模式,避免频繁的锁争夺。

class SingletonStatic{private:static const SingletonStatic* m_instance;SingletonStatic(){}public:static const SingletonStatic* getInstance(){return m_instance;}};//外部初始化 before invoke mainconst SingletonStatic* SingletonStatic::m_instance = new SingletonStatic;

 

 

特点与选择:

由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。

在访问量较小时,采用懒汉实现。这是以时间换空间。

转载于:https://www.cnblogs.com/guxuanqing/p/5876873.html

你可能感兴趣的文章
[Leetcode] Longest Substring Without Repeating Characters
查看>>
几款KINECT应用
查看>>
《JavaScript高级程序设计》chapter 1: javascript 简介
查看>>
利用日期、经纬度求日出日落时间 C语言程序代码(zz)
查看>>
atlas制作 和 自定义字体bnfont
查看>>
一本通1604理想的正方形
查看>>
实现全屏滑动返回效果
查看>>
ios8版本地图定位注意点
查看>>
模板模式
查看>>
CM12.1/13.0编译教程
查看>>
bjoi 2008 秦腾与教学评估
查看>>
使用 IntraWeb (9) - JavaScript
查看>>
u8货位补录
查看>>
B树、B-树、B+树、B*树 红黑树
查看>>
week two(2)—Learning Rate/polynomial regression /Normal Equation
查看>>
寻路 j2me
查看>>
让网站支持老版本IE6、7、8、9浏览器的3种解决方案
查看>>
一个可以模拟GET,POST,PUT,DELET请求的HTTP在线工具
查看>>
如何解决cacti的snmp error
查看>>
Linux下简单分析请求有没有进到本机的工具tcpdump(网络接口的数据包的头信息)...
查看>>