gpt4 book ai didi

c++ - 惰性初始化缓存...如何使其成为线程安全的?

转载 作者:可可西里 更新时间:2023-11-01 11:14:08 26 4
gpt4 key购买 nike

这就是我所拥有的:

  • Windows 服务
    • C#
    • 多线程
    • 服务使用读写锁(一次多次读取,写入会阻塞其他读/写线程)
  • 一个简单的、自写的数据库
    • C++
    • 足够小以适合内存
    • 足够大,不想在启动时加载它(例如 10GB)
    • 读取性能非常重要
    • 写作不太重要
    • 树状结构
    • 树节点中的信息存储在文件中
    • 为了更快的性能,文件仅在第一次使用和缓存时加载
    • 延迟初始化以加快数据库启动速度

由于数据库会非常频繁地访问这些节点信息(每秒几千次),而且我不经常写,所以我想使用某种双重检查锁定模式。

我知道这里有很多关于双重检查锁定模式的问题,但似乎有很多不同的意见,所以我不知道什么是最适合我的情况。你会用我的设置做什么?

这是一个例子:

  • 一棵有 100 万个节点的树
  • 每个节点存储一个键值对列表(存储在文件中以持久化,文件大小:10kB)
  • 当第一次访问一个节点时,列表被加载并存储在一个映射中(比如 std::map)
  • 下次访问这个节点时,我不需要再次加载文件,我只是从 map 上获取它。
  • 唯一的问题:两个线程第一次同时访问节点,想写入缓存映射。这不太可能发生,但并非不可能。这就是我需要线程安全的地方,它不应该花费太多时间,因为我通常不需要它(尤其是当整个数据库都在内存中时)。

最佳答案

关于双重检查锁定:

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;
}
}

它不是线程安全的,因为你检查资源的地址是否为空。因为在初始化指向它的资源对象之前,资源指针有可能被分配给一个非空值。

但是使用 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。根据this link指针分配在 x86 和 x64 系统中将是原子的。而 volatile 确保 resource 的值不会被缓存。

关于c++ - 惰性初始化缓存...如何使其成为线程安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8097439/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com