关于双重检查锁定:
class Foo
{
Resource * resource;
Foo() : resource(nullptr) { }
public:
Resource & GetResource()
{
if(resource == nullptr)
{
scoped_lock lock(mutex);
if(resource == nullptr)
resource = new Resource();
}
return *resource;
}
}
当您检查资源的地址是否为空时,它不是线程安全的。因为资源指针有可能在初始化指向它的 Resource 对象之前被分配给一个非空值。
但是使用 C++11 的“原子”特性,您可能会拥有双重检查锁定机制。
class Foo
{
Resource * resource;
std::atomic<bool> isResourceNull;
public:
Foo() : resource(nullptr), isResourceNull(true) { }
Resource & GetResource()
{
if(isResourceNull.load())
{
scoped_lock lock(mutex);
if(isResourceNull.load())
{
resource = new Resoruce();
isResourceNull.store(false);
}
}
return *resource;
}
}
编辑:没有原子
#include <winnt.h>
class Foo
{
volatile Resource * resource;
Foo() : resource(nullptr) { }
public:
Resource & GetResource()
{
if(resource == nullptr)
{
scoped_lock lock(mutex);
if(resource == nullptr)
{
Resource * dummy = new Resource();
MemoryBarrier(); // To keep the code order
resource = dummy; // pointer assignment
}
}
return *const_cast<Resource*>(resource);
}
}
MemoryBarrier()
确保dummy
将首先创建然后分配给resource
. 根据这个链接指针分配将在 x86 和 x64 系统中是原子的。并volatile
确保resource
不会缓存 的值。