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

我已经看到了Singleton模式的实现,其中实例变量在GetInstance方法中被声明为静态变量。像这样:


SomeBaseClass &SomeClass::GetInstance()

{

   static SomeClass instance;

   return instance;

}

我看到这种方法有以下积极方面:


代码更简单,因为只有第一次调用GetInstance时,编译器才负责创建此对象。

该代码更加安全,因为没有其他方法可以获取对实例的引用,但是可以使用GetInstance方法,并且没有其他方法可以更改实例,但是可以在GetInstance方法内部进行。

这种方法的负面影响是什么(除了这不是面向对象的)?这是线程安全的吗?


慕虎7371278
浏览 667回答 3
3回答

慕哥6287543

在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 _WIN32END Critical Section Here#endif     return instance;}

catspeake

根据规范,这也应在VC ++中工作。有人知道吗?只需添加关键字volatile。如果msdn上的文档正确,则可视c ++编译器应生成互斥体。SomeBaseClass &SomeClass::GetInstance(){   static volatile SomeClass instance;   return instance;}
打开App,查看更多内容
随时随地看视频慕课网APP