C++;单身人士—;不完全C++;11标准 我努力在C++中设计一个线程安全的单线程实现,但是它主要针对Visual Studio 2012环境。 我知道C++ 11标准保证了这个< /P> Foo& Instance() { static Foo instance; return instance; }
是线程安全的。但是VisualStudio 2012中使用的编译器还没有完全符合C++ 11标准(至少关于静态变量初始化的线程安全性)。所以我想到了这个:C++;单身人士—;不完全C++;11标准 我努力在C++中设计一个线程安全的单线程实现,但是它主要针对Visual Studio 2012环境。 我知道C++ 11标准保证了这个< /P> Foo& Instance() { static Foo instance; return instance; },c++,singleton,C++,Singleton,是线程安全的。但是VisualStudio 2012中使用的编译器还没有完全符合C++ 11标准(至少关于静态变量初始化的线程安全性)。所以我想到了这个: #include <iostream> #include <atomic> #include <mutex> class Foo { public: static Foo& Instance(); private: Foo() { init();
#include <iostream>
#include <atomic>
#include <mutex>
class Foo
{
public:
static Foo& Instance();
private:
Foo() { init(); }
Foo(Foo const&);
void operator = (Foo const&);
void init() { std::cout << "init done." << std::endl; }
static std::atomic<Foo*> _instance;
static std::mutex _mutex;
};
std::atomic<Foo*> Foo::_instance = nullptr;
std::mutex Foo::_mutex;
Foo& Foo::Instance()
{
if(_instance.load() == nullptr)
{
std::lock_guard<std::mutex> lock(_mutex);
if(_instance.load() == nullptr)
{
_instance = new Foo();
}
}
return *_instance;
}
#包括
#包括
#包括
福班
{
公众:
静态Foo&实例();
私人:
Foo(){init();}
Foo(Foo const&);
void运算符=(Foo const&);
void init(){std::cout双重检查锁定不是线程安全的。请参阅
与上述文章中的建议解决方案不同的替代解决方案:
T& thread_safe()
{
static std::once_flag once;
static T* result;
struct Initialize
{
static void apply(T*& result) { result = new T; }
};
std::call_once(once, Initialize::apply(result);
return *result;
}
注:
- 如果您没有std::call_one,您可以求助于boost等价物
- 您可以使用lambda,而不是使用本地结构
- 如问题中所述,没有必要使用符合C++11标准的编译器
在,您可以找到一篇关于该主题的优秀论文,包括一些简单的现成示例。您的代码与上一个类似,但可能不正常,因为您没有使用.store()
方法将指针复制到新创建的实例。它也可能不会生成最佳的机器指令。这是旧的单例反模式。在检查单例是否仍然为空之前,必须锁定互斥体。你说得对,谢谢。我想我们应该在实际测试if(\u instance.load()之前锁定互斥体==nullptr)
我们是安全的,对吗?但是不是std::once_标志
C++11?在这种情况下,原始代码不是安全的吗?@Galik使用std::once_标志来确保线程安全的初始化不同于静态变量初始化(根据C++11,线程安全,但在msvc 2013中不安全)侧注:一个不错的链接