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

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

/*    代码中经常会使用到单例模式,单例模式就是隐藏构造函数,提供获取一个实例的静态方法。    但是在多线程场景下,单例模式会有一些不同。例如Config类的instance方法如下    */    //获取一个实例(对外接口)    static Config * instance()    {        if (NULL == m_instance)        {            //加锁(多线程场景下)            m_mutex.acquire();            if (NULL == m_instance)            {                m_instance = new Config();                /*                类似于这个类的初始化,我是不建议放在这里的,                因为如果init方法执行失败,但是实例仍然不为NULL,                建议在main函数中第一次调用instance方法时,执行init方法初始化实例                (注意init方法也是只能执行一次的,请考虑多线程场景)                init方法放在这个纯粹是为了解释这个场景下单例的使用                */                m_instance->init();            }            //解锁            m_mutex.release();        }        return m_instance;    }
/*如果在instance方法中不加锁,在多线程的场景下,有可能创建出多个实例。instance方法在加锁之后,还是有问题的。假设线程A正在执行m_instance->init()方法(init方法执行的时间很长),此时线程B开始执行instance方法,发现m_instance != NULL(因为线程A已经构造了该实例),那么线程B就会直接获取到这个并没有执行完init方法的m_instance实例,线程B用这个m_instance去执行操作,就会出现问题。*/

 

/*简单的改进就是,去掉前边的判断,直接加锁,这样就避免了该问题,线程B进行进来的时候因为线程A已经获取到锁,线程B会等待,等到线程A释放锁之后(所有初始化操作已经完成),线程B判断m_instance != NULL,线程B可以使用m_instance这个实例了*/static Config * Config::instance(){    //加锁(多线程场景下)    m_mutex.acquire();    if (NULL == m_instance)    {        m_instance = new Config();        m_instance->init();    }    //解锁    m_mutex.release();     return m_instance;}
/*但是这样的改进会出现一个新问题,就是每次调用这个单例就会加锁判断,频繁调用会影响速度*/

 

/*    再次改进方案,使用一个临时变量构造,初始化,成功后再赋值给m_instance    这样避免了多线程操作影响,又不影响速度    */    static Config * instance()    {        if (NULL == m_instance)        {            //加锁(多线程场景下)            m_mutex.acquire();            if (NULL == m_instance)            {                Config * pInstance = new Config();                pInstance->init();                m_instance = pInstance;            }            //解锁            m_mutex.release();        }        return m_instance;    }

 

转载地址:http://eskio.baihongyu.com/

你可能感兴趣的文章
Java中的泛型 --- Java 编程思想
查看>>
javaScript跨浏览器事件处理程序
查看>>
Angular学习笔记
查看>>
WebView 支持 Html5 video 进行全屏播放
查看>>
设计模式 之 中介者模式
查看>>
项目启动之spring篇
查看>>
图像数据增强方法一览(附python代码)
查看>>
socket异步编程--libevent的使用
查看>>
帮你偷懒的靠谱幻灯工具
查看>>
【学习笔记】hive 之行拆列explode
查看>>
【vue】指令修饰符,键盘事件,阻止默认事件,阻止事件传播
查看>>
区块链开发公司浅析区块链技术给保险行业的创新
查看>>
NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang
查看>>
【Linux】CentOS操作和问题汇总
查看>>
nginx负载均衡配置
查看>>
最近重新阅读了逻辑回归,有一些感触
查看>>
数据驱动编程之表驱动法
查看>>
向量的相关运算和几何意义(扫盲篇)
查看>>
Linux设备模型 (4)
查看>>
iOS报错:linker command failed with exit code 1 (use -v to see invocation)
查看>>