• c++——线程安全的单例


    方式1—静态局部变量实现单例

    线程安全,c++11之后支持。实现代码如下:

    class Singleton
    {
    public:
        static Singleton *getInstance()
        {
            static Singleton instance;
            return &instance;
        }
    private:
        Singleton() {}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    局部静态变量的初始化时机:

    • 发生在函数第一次被调用到局部静态变量定义语句时;

    静态局部变量的特点:

    • 在全局数据区分配内存;
    • 静态局部变量一般在声明时初始化,如果没有被显式初始化,会被程序自动初始化为0;

    在c++98/03标准中,不是线程安全的,实际实现代码如下:

    static Singleton& getInstance()
    {
        static bool initialized = false;
        static char buf[sizeof(Singleton)];
    
        if (!initialized) {
            initialized = true;
            new(&buf) Singleton();
        }
    
        return (*(reinterpret_cast( &buf)));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    c++11后做了改进,保证了线程安全,大概描述如下:

    such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
    
    • 1

    主要实现方式:

    • 在当前线程执行到需要初始化变量的地方时,如果有其他线程正在初始化该变量,则阻塞当前线程,直到初始化完成为止。

    方式2—std::call_once

    线程安全,c++11之后支持。实现代码如下:

    class Singleton
    {
    public:
       static Singleton& getInstance()
       {
           static std::once_flag s_flag;
           std::call_once(s_flag,[&](){
            m_instance.reset(new Singleton());
           });
           return *m_instance;
       }
        
       ~ Singleton() = default;
        
    private:
       Singleton() = default;
       Singleton& operator=(const Singleton&) = delete;
       Singleton(const Singleton&) = delete;
        
    private:
       static std::unique_ptr m_instance;
    }
    
    std::unique_ptr Singleton::m_instance;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    MySQL 表的增删查改
    zabbix部署及监控
    Cmake qt ,vtkDataArray.cxx.obj: File too big
    如何通过日志切分优雅实现业务数据的提取和分析
    SpringBoot打包部署最佳实践
    信创之国产浪潮电脑+统信UOS操作系统体验4:visual studio code中怎么显示中文
    Linux:1.进程介绍+2.Linux父子进程+3.终止进程kill和killall+4.查看进程树pstree+5.service服务管理
    【计算机网络】第四章:网络层 (万字详解)
    如何看懂SparkUI?
    自恢复集群启动命令oninitdb的设计与实现:
  • 原文地址:https://blog.csdn.net/www_dong/article/details/126294744