C++ 双重锁定解决方案
我想惰性地实例化一个C++ 双重锁定解决方案,c++,multithreading,thread-safety,C++,Multithreading,Thread Safety,我想惰性地实例化一个ViewportFactory,如下所示: ViewportFactory* RenderObjectFactory::GetViewportFactory() { if (viewportFactory == nullptr) { std::lock_guard<std::mutex> instantiationLockGuard { factoryInstantiationMutex }; if (viewportFac
ViewportFactory
,如下所示:
ViewportFactory* RenderObjectFactory::GetViewportFactory() {
if (viewportFactory == nullptr) {
std::lock_guard<std::mutex> instantiationLockGuard { factoryInstantiationMutex };
if (viewportFactory == nullptr) {
switch (GetAndCommitRenderingAPISelection()) {
case 0:
ViewportFactory* v = new DirectXViewportFactory { };
viewportFactory = v;
break;
}
}
}
return viewportFactory;
}
ViewportFactory*RenderObjectFactory::GetViewportFactory(){
如果(viewportFactory==nullptr){
std::lock_guard实例化lockguard{factoryInstantiationMutex};
如果(viewportFactory==nullptr){
开关(GetAndCommitTrenderInGapiSelection()){
案例0:
ViewportFactory*v=新的DirectXViewportFactory{};
视口工厂=v;
打破
}
}
}
返回视口工厂;
}
这足够安全吗?我的想法是,只要分配
viewportFactory
,只要新的DirectXViewportFactory
被正确实例化,它就是…我认为这是不安全的。通过优化viewportFactory
,仍然可以在调用构造函数之前为已分配但未初始化的内存分配指针。请参见中的示例6
即使是安全的,该代码也不便于维护。当稍后有人出现时,可能是您或完全不熟悉它的人,很容易在错误的位置添加代码,从而引入竞争条件。这些bug很难复制和隔离——性能提升真的值得冒这个风险吗
正如@DieterLücking所提示的,可以使用局部静态变量实现惰性实例化,这在C++11标准中是线程安全的。您必须小心,您的编译器实际上实现了标准的这一部分-对于Visual Studio(因为您似乎在Windows上),这种情况直到发生时才发生。目前的代码不是线程安全的。编译器可以自由地优化连续的空检查,因为指针从未在同一线程上更改
我认为使用c++11实现这一点的建议方法是使用std::call_一次或使用静态变量。有关示例,请参见。另外:“足够线程安全”?方法要么是线程安全的,要么不是。为什么viewportFactory不是函数的静态局部?@DieterLücking直到VS2013(2013年11月发布)才在Visual Studio中强制执行局部静态变量的线程安全初始化。OP可能需要使用较旧的编译器生成。