延迟初始化缓存..我如何使它线程安全
Lazy initialized caching... how do I make it thread-safe?
这就是我所拥有的:
- 一个Windows服务
- c# 多线程
- 服务使用Read-Write-Lock(一次读多个,写阻塞其他读写线程)
一个简单的,自己编写的数据库 - 足够小,可以装入内存
- 足够大,不想在启动时加载它(例如10GB)
- 读性能非常重要
- 文字不那么重要
- 树结构
- 树节点中的信息存储在文件 中
- 为了更快的性能,文件只在第一次使用时加载并缓存
- 延迟初始化以加快数据库启动
- c++
由于DB将非常频繁地访问这些节点信息(每秒数千次),并且由于我不经常写入,因此我希望使用某种双重检查锁定模式。
我知道这里有很多关于双重检查锁定模式的问题,但是似乎有很多不同的意见,所以我不知道什么对我的情况是最好的。你会怎么处理我的装置?
下面是一个例子:
- 拥有100万个节点的树
- 每个节点存储一个键值对列表(存储在一个文件中用于持久化,文件大小大小:10kB)
- 当第一次访问一个节点时,列表被加载并存储在一个映射中(类似std::map)
- 下一次访问这个节点时,我不需要再次加载文件,我只需要从地图中获取它。
- 唯一的问题:两个线程第一次同时访问节点,并且想要写入缓存映射。这种情况不太可能发生,但也不是不可能。这就是我需要线程安全的地方,它不应该花费太多时间,因为我通常不需要它(特别是当整个DB都在内存中时)。
关于双重检查锁定:
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;
}
}
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()
确保首先创建dummy
,然后将其分配给resource
。根据这个链接指针的分配在x86和x64系统中是原子的。volatile
保证resource
的值不被缓存
您是否在问如何使读取DB或读取节点线程安全?
如果你正在尝试后者,并且你不经常写,那么为什么不让你的节点不可变呢?如果您需要写一些东西,那么从现有节点复制数据,修改它并创建另一个节点,然后您可以将其放入数据库。
相关文章:
- 学习多线程C++:添加线程不会使执行速度更快,即使它看起来应该
- 如何使缓存线程安全
- 使来自线程的数据流对所有其他线程都可读
- 分离线程然后让它超出范围(并使其仍在运行)是否安全?
- 如何使一个线程中的内存存储"promptly"在其他线程中可见?
- 如何使一个线程按预期顺序多次等待另一个线程
- 如何使用pthreads使多线程正常工作,而不是使用C++在类中提升
- 如何使boost ::线程入睡
- 如何将数据传输到另一个线程并使helgrind知道它
- 如何使生成的线程拖延足够长的时间以使生成线程执行某些操作
- 将函数放在类中,然后声明"New"是否使其线程安全?
- 多个线程同时在unordered_map中添加值会使它崩溃
- TCLAP使多线程程序速度变慢
- CRT参数验证使多线程调试程序崩溃
- PC多线程性能和稳定性问题的简单基准测试.如何使每个线程在单独的核心上运行
- 延迟初始化缓存..我如何使它线程安全
- 在这种情况下如何使shared_ptr线程安全
- 如何在C++11中使每个线程使用自己的RNG
- 如何使一个线程在MFC中移动滑块控件相对于正在播放的音频文件
- 我可以锁定列表中的一个元素以使其线程安全,而不是锁定整个列表吗?