C++如何实现一个线程安全的单例

方法(1):

    static SingletionClass* Instance()
    {
        Locker locker;
        if (m_spInstance == NULL)
        {
            m_spInstance = new CShopMgrImpl;
        }

        return m_spInstance;
    }

弊端:每次都需要锁,对性能有些影响

 

方法(2):

    static SingletionClass* Instance()
    {
        if (m_spInstance == NULL)
        {
            Locker locker;
            if (m_spInstance == NULL)
            {
                m_spInstance = new CShopMgrImpl;
            }
        }

        return m_spInstance;
    }

DCL(双重检测锁)实现,目前已经被证明是存在问题的。参考 "4.双重检查带来的问题"

 

方法(3):

    static SingletionClass* Instance() {
        static std::once_flag flag;
        std::call_once(flag, [&] {
            m_spInstance = new SingletionClass;
        });

        return m_spInstance;
    }

使用c++11新特性,std::call_once 函数实现

问题:static std::once_flag flag  这个是静态变量,多线程访问不会有问题吗?

回答:不会,c++11已经保证静态变量初始化线程安全,参考"3.c++11对静态变量初始化线程安全的保证:"

 

方法(4):

static SingletionClass* getInstance(){
    SingletionClass* sin= instance.load(std::memory_order_acquire);
    if ( !sin ){
      std::lock_guard<std::mutex> myLock(myMutex);
      sin= instance.load(std::memory_order_relaxed);
      if( !sin ){
        sin= new SingletionClass();
        instance.store(sin,std::memory_order_release);
      }
    }   
    // volatile int dummy{};
    return sin;
  }

这个地方使用了内存栅栏技术,避免了双重检查锁带来的问题。

这个也是https://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf这篇论文中提到的使用内存栅栏的解决方法。

相关知识点书籍推荐:

《深入理解C++11:C++11新特性解析与应用》

https://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

 

 

1.类似的问题讨论以及参考:

https://spikez.tistory.com/349

https://www.modernescpp.com/index.php/thread-safe-initialization-of-a-singleton

 

2.内存栅栏:

https://preshing.com/20120710/memory-barriers-are-like-source-control-operations/

 

3.c++11对静态变量初始化线程安全的保证:

https://iamroman.org/blog/2017/04/cpp11-static-init/

https://stackoverflow.com/questions/1270927/are-function-static-variables-thread-safe-in-gcc

https://blog.csdn.net/imred/article/details/89069750

 

4.双重检查带来的问题:

https://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

c++11给出的解决方案:

https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/

chrome给出的解决方案:

https://www.jianshu.com/p/3f6355cdd739

java的解决方案:

https://www.jianshu.com/p/8b580d20dd58

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值