为了账号安全,请及时绑定邮箱和手机立即绑定

声明为GetInstance方法的静态变量的Singleton实例,它是线程安全的吗?

声明为GetInstance方法的静态变量的Singleton实例,它是线程安全的吗?

慕虎7371278 2019-12-25 10:50:59
我已经看到了Singleton模式的实现,其中实例变量在GetInstance方法中被声明为静态变量。像这样:SomeBaseClass &SomeClass::GetInstance(){   static SomeClass instance;   return instance;}我看到这种方法有以下积极方面:代码更简单,因为只有第一次调用GetInstance时,编译器才负责创建此对象。该代码更加安全,因为没有其他方法可以获取对实例的引用,但是可以使用GetInstance方法,并且没有其他方法可以更改实例,但是可以在GetInstance方法内部进行。这种方法的负面影响是什么(除了这不是面向对象的)?这是线程安全的吗?
查看完整描述

3 回答

?
慕哥6287543

TA贡献1831条经验 获得超10个赞

在C ++ 11中,它是线程安全的:


§6.7[stmt.dcl] p4如果在初始化变量的同时控件同时输入声明,则并发执行应等待初始化完成。


在C ++ 03中:


在g ++下,它是线程安全的。

但这是因为g ++显式添加了代码来保证它。

一个问题是,如果您有两个单例,并且它们在构造和销毁过程中相互尝试使用。


阅读本文: 查找C ++静态初始化顺序问题


此问题的一个变体是,是否从全局变量的析构函数访问单例。在这种情况下,单例无疑已被破坏,但是get方法仍将返回对被破坏对象的引用。


有很多解决方法,但是它们很杂乱,不值得做。只是不要从全局变量的析构函数访问单例。


一个更安全的定义但很丑陋:

我敢肯定您可以添加一些适当的宏来整理一下


SomeBaseClass &SomeClass::GetInstance()

{

#ifdef _WIN32 

Start Critical Section Here

#elif  defined(__GNUC__) && (__GNUC__ > 3)

// You are OK

#else

#error Add Critical Section for your platform

#endif


    static SomeClass instance;


#ifdef _WIN32

END Critical Section Here

#endif 


    return instance;

}


查看完整回答
反对 回复 2019-12-25
?
catspeake

TA贡献1111条经验 获得超0个赞

根据规范,这也应在VC ++中工作。有人知道吗?


只需添加关键字volatile。如果msdn上的文档正确,则可视c ++编译器应生成互斥体。


SomeBaseClass &SomeClass::GetInstance()

{

   static volatile SomeClass instance;

   return instance;

}


查看完整回答
反对 回复 2019-12-25
  • 3 回答
  • 0 关注
  • 706 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信