zoukankan      html  css  js  c++  java
  • 【C++设计模式】单件类与DCLP(Double Check Lock Pattern)的风险

    【单件类】
      保证只能有一个实例化对象,并提供全局的访问入口。
    【设计注意事项】
      1.阻止所有实例化的方法:
        private 修饰构造函数,赋值构造函数,赋值拷贝函数。
      2.定义单实例化对象的方法:
        a.使用static 修饰
        b.使用new+delete的方法
      3.多线程版本:
        使用双检测锁定,即先检测单实例对象是否存在;不存在,使能“锁”,再次判断实例是否存在,不存在就创建该单实例对象。
      A.单层锁示例:
    Singleton* Singleton::getInstance() { 
        Lock lock;      // scope-based lock, released automatically when the function returns 
        if (m_instance == NULL) { 
            m_instance = new Singleton; 
        } 
        return m_instance; 
    } 
      B.DCL示例:【单层锁存在高并发时效率低,DCL提出先检测单件指针m_instance是否已创建,减少大部分的锁;上锁后,再次检查m_instance 】
     
    Singleton* Singleton::getInstance() { 
    if(m_instance==NULL)
    {
      Lock lock;      // scope- based lock, released automatically when the function returns 
        if (m_instance == NULL) { 
            m_instance = new Singleton; 
        } 
    }
       
        return m_instance; 
    } 
    【DCL的风险】
    回顾下(或者学习下)   m_instance = new Singleton; 发生了什么:
      1.分配Singleton对象所需的内存
      2.为该内存区域执行构造函数
      3.m_instance指向该内存。
      一切都似乎没有什么问题,但是有时编译器喜欢把2和3替换下(先不管编译器出于什么目的)
    执行单例化构造( m_instance = new Singleton; )的顺序中,其他线程访问对象程序未加锁【lock一般不阻止CPU线程调度程序,只对俩个线程里同样上了同个锁的部分函数有阻塞作用】,直接访问会出故障【操作未定义的对象】,又不能所有地方都加锁--效率低。
    解决方法:在单例化构造中先构造给临时变量,再把临时变量赋值给单例化对象的指针,注意防止编译器优化,否则前功尽弃【当然,这种方式的弊端目前尚未考虑到】。
     
    Singleton* Singleton::getInstance() { 
       volatile Singleton* tmp = m_instance; 
        ...                     // insert memory barrier 
        if (tmp == NULL) { 
            Lock lock; 
            tmp = m_instance; 
            if (tmp == NULL) { 
                tmp = new Singleton; 
                ...             // insert memory barrier 
                m_instance = tmp; 
            } 
        } 
        return tmp; 
    } 
    【背景知识】
      2000年,一个JAVA高性能研究小组发布了一篇声明《双重检查锁定可能导致锁定无效》。
      2004年,Scott Meyers 和Andrei Alexandrescu联合发表了一篇名为《C++实现双重检查锁定存在严重缺陷
    【参考链接】
    知行合一
  • 相关阅读:
    买房的贷款时间是否是越长越好?https://www.zhihu.com/question/20842791
    asp.net cookie and session
    leelazero and google colab
    download file by python in google colab
    physical processor, core, logical processor
    通过powershell操作eventlog
    openxml in sql server
    get the page name from url
    How to Execute Page_Load() in Page's Base Class?
    Difference between HttpContext.Request and Request
  • 原文地址:https://www.cnblogs.com/guiguzhixing/p/6052844.html
Copyright © 2011-2022 走看看