• C++ 单例模式实现


    C++ 单例模式(懒汉、饿汉模式)

    C++实现单例模式(包括采用C++11中的智能指针)

    饿汉模式:

    class CSingleton    
    {    
    private:    
        CSingleton()      
        {    
        }    
    public:    
        static CSingleton * GetInstance()    
        {    
            static CSingleton instance;     
            return &instance;    
        }    
    };
    ————————————————
    版权声明:本文为CSDN博主「zhanghuaichao」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zhanghuaichao/article/details/79459130

    多线程下的懒汉模式

    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;  
    }
    ————————————————
    版权声明:本文为CSDN博主「zhanghuaichao」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zhanghuaichao/article/details/79459130

    懒汉:故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化。与之对应的是饿汉式单例。(注意,懒汉本身是线程不安全的,如上例子)

    饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。(本身就是线程安全的,如下例子)

    关于如何选择懒汉和饿汉模式:

    特点与选择:

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

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

    3、饿汉式的单例实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #include <iostream>
    #include <process.h>
    #include <windows.h>
    using namespace std;
     
    class Singelton{
    private:
        Singelton(){
            m_count ++;
            printf("Singelton begin ");
            Sleep(1000);                            // 加sleep为了放大效果
            printf("Singelton end ");
        }
        static Singelton *single;
    public:
        static Singelton *GetSingelton();
        static void print();
        static int m_count;
    };
    // 饿汉模式的关键:初始化即实例化
    Singelton *Singelton::single = new Singelton;
    int Singelton::m_count = 0;
     
    Singelton *Singelton::GetSingelton(){
        // 不再需要进行实例化
        //if(single == nullptr){
        //    single = new Singelton;
        //}
        return single;
    }
     
    void Singelton::print(){
        cout<<m_count<<endl;
    }
    // 回调函数
    void threadFunc(void *p){
        DWORD id = GetCurrentThreadId();        // 获得线程id
         cout<<id<<endl;
        Singelton::GetSingelton()->print();      // 构造函数并获得实例,调用静态成员函数
    }
     
    int main(int argc, const char * argv[]) {
        int threadNum = 3;
        HANDLE threadHdl[100];
         
        // 创建3个线程
        for(int i = 0; i<threadNum; i++){
            threadHdl[i] = (HANDLE)_beginthread(threadFunc, 0, nullptr);
        }
         
        // 让主进程等待所有的线程结束后再退出
        for(int i = 0; i<threadNum; i++){
            WaitForSingleObject(threadHdl[i], INFINITE);
        }
        cout<<"main"<<endl;                 // 验证主进程是否是最后退出
        return 0;
    }

      运行结果:

    4、线程安全的懒汉式单例的实现

    饿汉式会提前浪费我们的内存空间以及资源,如果有项目中要求我们在使用到实例的时候再去实例化,则还是需要使用懒汉式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class singleton
    {
    protected:
        singleton()
        {
            // 初始化
            pthread_mutex_init(&mutex);
        }
    private:
        static singleton* p;
    public:
        static pthread_mutex_t mutex;
        static singleton* initance();
    };
     
    pthread_mutex_t singleton::mutex;
    singleton* singleton::p = NULL;
    singleton* singleton::initance()
    {
        if (p == NULL)
        {
            // 加锁
            pthread_mutex_lock(&mutex);
            if (p == NULL)
                p = new singleton();
            pthread_mutex_unlock(&mutex);
        }
        return p;
    }

      需要注意的是:上面进行的两次if(p == NULL)的检查,因为当获得了实例之后,有了外层的判断之后,就不会再进入到内层判断,即不会再进行lock以及unlock的操作。

  • 相关阅读:
    2014第2周四部署环境&买火车票
    2014第2周三Web安全学习
    2014第2周二
    2014第2周一
    2013第一周日小结
    2013第1周六意外加班到很晚
    2014第一周五开发问题记URL传参乱码等
    XML文档形式&JAVA抽象类和接口的区别&拦截器过滤器区别
    通过WriteProcessMemory改写进程的内存
    【java】Windows7 下设置环境变量
  • 原文地址:https://www.cnblogs.com/sylar5/p/11520505.html
Copyright © 2020-2023  润新知