美文网首页
单例模式

单例模式

作者: 吃掉夏天的怪物 | 来源:发表于2021-09-09 17:07 被阅读0次

    单例模式
    保证全局唯一性,得考虑线程安全性
    延迟加载?

    饿汉模式

    线程安全的,但是不支持延迟加载(有问题早发现)
    ① //指针

    #include<iostream>
    #include<algorithm>
    #include<mutex>
    
    using namespace std;
    //饿汉
    class Singleton{
        public:
            static Singleton* getInstance();
        private:
            Singleton(){
                cout<<"new";
            }
            Singleton(const Singleton&) =delete;
            Singleton operator =(const Singleton&) = delete;
            
            static Singleton* instance;
    };
    Singleton* Singleton::instance = new Singleton();
    Singleton* Singleton::getInstance(){
        return instance;
    }
    int main(){
        Singleton *s = Singleton::getInstance();
        Singleton *ss = Singleton::getInstance();
        Singleton *sss = Singleton::getInstance();
        return 0; 
    }
    

    ② 引用

    #include<iostream>
    #include<algorithm>
    #include<mutex>
    
    using namespace std;
    //饿汉
    class Singleton{
        public:
            static Singleton& getInstance();
            ~Singleton(){cout<<"out"<<endl;}
        private:
            Singleton(){
                cout<<"new"<<endl;
            }
            Singleton(const Singleton&) =delete;
            Singleton operator =(const Singleton&) = delete;
            
            static Singleton instance;
    };
    Singleton Singleton::instance;
    Singleton& Singleton::getInstance(){
        return instance;
       
    }
    int main(){
        Singleton& s = Singleton::getInstance();
        Singleton& ss = Singleton::getInstance();
        Singleton& sss = Singleton::getInstance();
        return 0; 
    }
    

    懒汉模式

    可以实现延迟加载
    ① 简单加锁,存在指令重排的问题
    new Singleton并不是一个原子性的操作,可以分为1.找到空间2.构造 3.返回,一般在X86架构下CPU会对其优化使得实际执行顺序位1,3,2。当多线程时线程A调用了构造函数此时实际执行中的2还没执行完,那么B在条件判断时就会认为instance == nullptr从而产生问题。JAVA和C#,win->C++通过(volatile?还是啥没听清反正就是有办法解决这个问题),其它情况就只能通过复杂的原子操作来告诉CPU不要进行优化。但是利用C++11 static 的线程安全特性可以解决这个问题。

    #include<iostream>
    #include<algorithm>
    #include<mutex>
    
    using namespace std;
    //懒汉  -- 简单加锁              ----->     会导致指令重排
    class Singleton{
        public:
            static Singleton* getInstance();
        private:
            Singleton(){
                cout<<"new";
            }
            Singleton(const Singleton&) =delete;
            Singleton operator =(const Singleton&) = delete;
            
            static Singleton* instance;
            static mutex m_mutex;
    };
    Singleton* Singleton::instance = nullptr;//
    mutex Singleton::m_mutex;
    Singleton* Singleton::getInstance(){//A,B 需要考虑线程安全
        if(instance == nullptr){
            lock_guard<mutex> lock(m_mutex);
            if(instance == nullptr){
                instance = new Singleton;// 对于底层并不是原子性呢
                //1.find 找到空间
                //2.alloc 开始构造
                //3. return 
    
                //x86中会有优化 跟着CPU走的问题,后来JAVA和C#解决了这个问题 win->C++ volatile解决了这个问题
                //其它情况下得告诉CPU不要进行优化,原子操作
                //1.find
                //2. return 
                //3. alloc
    
                //C++ 11 static 线程安全
    
            }
        }
        
        return instance;
    }
    int main(){
        Singleton *s = Singleton::getInstance();
        Singleton *ss = Singleton::getInstance();
        Singleton *sss = Singleton::getInstance();
        return 0; 
    }
    

    ② 利用C++11 static线程安全特性

    #include<iostream>
    #include<algorithm>
    #include<mutex>
    
    using namespace std;
    //懒汉 C++ 11 static 线程安全
    class Singleton{
        public:
            ~Singleton(){
                cout<<"out"<<endl;
            };
            static Singleton& getInstance(){
                static Singleton instance;
                return instance;
            }
    
        private:
            Singleton(){
                cout<<"new";
            }
            Singleton(const Singleton&) =delete;
            Singleton operator =(const Singleton&) = delete;
            
      
    };
    
    
    int main(){
        Singleton &s = Singleton::getInstance();
        Singleton &ss = Singleton::getInstance();
        Singleton &sss = Singleton::getInstance();
        return 0; 
    }
    

    视频后的笔记

    相关文章

      网友评论

          本文标题:单例模式

          本文链接:https://www.haomeiwen.com/subject/fxaiwltx.html