[英]Lazy initialized caching… how do I make it thread-safe?
that's what I have: 那就是我所拥有的:
As the DB will access those node informations very often (in the magnitude of several thousand times a second) and as I don't write very often, I'd like to use some kind of double checked locking pattern. 由于DB非常频繁地访问这些节点信息(每秒几千次),并且由于我不经常编写,所以我想使用某种双重检查的锁定模式。
I know there is many questions about the double checked locking pattern here, but there seems to be so many different opinions, so I don't know what's the best for my case. 我知道这里有很多关于双重检查锁定模式的问题,但是似乎有很多不同的意见,所以我不知道哪种方法最适合我的情况。 What would you do with my setup? 您如何处理我的设置?
Here's an example: 这是一个例子:
About double checked locking: 关于双重检查锁定:
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;
}
}
It is not thread-safe as you check whether the address of resource is null. 当您检查资源地址是否为空时,它不是线程安全的。 Because there is a chance that resource pointer is assigned to a non-null value right before the initializing the Resource object pointed to it. 因为在初始化指向它的Resource对象之前,有可能将资源指针分配给非空值。
But with the "atomics" feature of C++11 you may have a doubly checked locking mechanism. 但是,使用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;
}
}
EDIT: Without atomics 编辑:没有原子
#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()
ensures that dummy
will be first created then assigned to resource
. MemoryBarrier()
确保将首先创建dummy
然后将其分配给resource
。 According to this link pointer assignments will be atomic in x86 and x64 systems. 根据此链接,在x86和x64系统中,指针分配是原子的。 And volatile
ensures that the value of resource
will not be cached. 而volatile
确保不会缓存resource
的值。
Are you asking how to make reading the DB or reading the Nodes thread safe? 您是在问如何使读取DB或读取Nodes线程安全吗?
If you're trying to the latter and you're not writing very often, then why not make your nodes immutable , period? 如果您尝试使用后者而又写得不是很频繁,那为什么不让节点不可变 ? If you need to write something, then copy the data from the existing node, modify it and create another node which you can then put in your database. 如果需要编写某些内容,请从现有节点复制数据,进行修改并创建另一个节点,然后将其放入数据库中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.