• 关于DCLP实现的单例模式的一些想法


    关于DCLP实现的单例模式的一些想法

    我之前写过单例的文章( http://www.cnblogs.com/mkdym/p/4908644.html ),但是现在又有了一些想法,不想再在原来那篇文章上更新,所以独开一篇。

    看到一些书或者文章讲单例模式的时候,总要说起DCLP,并且得出的结论是DCLP是不可靠的,也就不能用它来实现单例。即下面这样做是错误的:

    class SingletonAA
    {
    public:
        static SingletonAA& get_instance_ref()
        {
            if (NULL == p_) // 1st check
            {
                scoped_lock lock;
                if (NULL == p_) // 2nd check
                {
                    p_ = new SingletonAA();
                }
            }
            return *p_;
        }
    
    private:
        SingletonAA()
        {
            //...
        }
    
        ~SingletonAA()
        {
            //...
        }
    
    private:
        static SingletonAA *p_;
    
    };
    
    SingletonAA *SingletonAA::p_ = NULL;

    因为new那一句不是原子的,分了3步,而且顺序不一定,这个顺序又会影响第一次检查的结果。接着他们又讨论了volatile关键字和乱序优化,然后得出结论这个关键字也不能使DCLP变得正确,或者说不能轻松的使DCLP变得正确。

    但是他们讲这个问题的时候全部的前提是用单例对象的指针本身去做了判断条件,这就是诱因:单例对象的创建和单例的判断是对同一个元素读写,而“写”太“复杂”了!

    那么我不用单例对象去做判断不就行了吗?如下:

    class SingletonAA
    {
    public:
        static SingletonAA& get_instance_ref()
        {
            if (!init_flag_) // 1st check
            {
                scoped_lock lock;
                if (!init_flag_) // 2nd check
                {
                    p_ = new SingletonAA();
                    init_flag_ = true;
                }
            }
            return *p_;
        }
    
    private:
        //...
    
    private:
        static SingletonAA *p_;
        static bool volatile init_flag_;
    };
    
    SingletonAA *SingletonAA::p_ = NULL;
    bool volatile SingletonAA::init_flag_ = false;

    我换用一个bool标志,bool变量在vc上是一个字节的,操作只需一条指令,是原子的。而且声明成volatile,确保编译器不对它做优化。

    按我的不准确的知识,编译器或CPU可能会对

    p_ = new SingletonAA();

    init_flag_ = true;

    这两句调整顺序,因为他们两句没有关联,这就又会出错。那么我制造一个关联:

    init_flag_ = p_ ? true : false;

    使init_flag_的赋值依赖于对象的创建,按我的理解,此时编译器和CPU都应该使设置标志语句后于对象创建语句,那么就没有错误了。

    假如编译器认为p_在执行完new后一定不为0,那么它就又可以优化init_flag_的赋值了。那么这种情况会不会出现,编译器是否会这样认为?

    Need Help

    Need Help

    Need Help

    (重说三)

    因为我想得到大家的关注,所以可耻的勾选了“发布至博客园首页”,如果最后没有在首页出现,我就把这句话删掉,免的丢我的小脸。

  • 相关阅读:
    win7桌面的文件路径是否可以更改
    win10怎么更新flash到最新版本【系统天地】
    centos7 lnmp环境部署
    thinkphp5 部署注意事项
    linux下导入、导出mysql数据库命令的实现方法
    Centos7 系统下怎么更改apache默认网站目录
    centos7 配置lamp 环境
    Redis笔记(4)独立功能的实现
    Redis笔记(3)多数据库实现
    Redis笔记(2)单机数据库实现
  • 原文地址:https://www.cnblogs.com/mkdym/p/4961543.html
Copyright © 2020-2023  润新知