Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在不阻塞的情况下更新缓存_C++_Multithreading_C++11_Shared Ptr - Fatal编程技术网

C++ 在不阻塞的情况下更新缓存

C++ 在不阻塞的情况下更新缓存,c++,multithreading,c++11,shared-ptr,C++,Multithreading,C++11,Shared Ptr,我目前有一个程序,它有一个类似缓存的机制。我有一个线程正在侦听从另一台服务器到此缓存的更新。此线程将在收到更新时更新缓存。下面是一些伪代码: void cache::update_cache() { cache_ = new std::map<std::string, value>(); while(true) { if(recv().compare("update") == 0) { std::map&

我目前有一个程序,它有一个类似缓存的机制。我有一个线程正在侦听从另一台服务器到此缓存的更新。此线程将在收到更新时更新缓存。下面是一些伪代码:

void cache::update_cache()
{
    cache_ = new std::map<std::string, value>();
    while(true)
    {
        if(recv().compare("update") == 0)
        {
            std::map<std::string, value> *new_info = new std::map<std::string, value>();
            std::map<std::string, value> *tmp;
            //Get new info, store in new_info
            tmp = cache_;
            cache_ = new_cache;
            delete tmp;              
        }
    }
}

std::map<std::string, value> *cache::get_cache()
{
    return cache_;
}
void cache::update_cache()
{
缓存=新的std::map();
while(true)
{
如果(recv().compare(“update”)==0)
{
std::map*new_info=new std::map();
std::map*tmp;
//获取新信息,存储在新信息中
tmp=高速缓存;
缓存=新缓存;
删除tmp;
}
}
}
标准::映射*缓存::获取缓存()
{
返回缓存;
}
正在同时从多个不同的线程读取缓存。我相信,如果我的一个线程调用
get\u cache()
,然后我的缓存更新,然后线程尝试访问存储的缓存,我将遇到未定义的行为

我正在寻找一种方法来避免这个问题。我知道我可以使用互斥锁,但我不想阻止读取的发生,因为它们必须尽可能低的延迟,但如果需要,我可以这样做

我想知道这是否是一个独特的ptr的好用例。我的理解正确吗?如果线程调用get_cache,并返回一个唯一的_ptr而不是标准指针,那么一旦所有具有旧版本缓存的线程都使用完它(即离开作用域),对象将被删除

对于这种情况,使用唯一的ptr是最好的选择,还是我没有想到的其他选择

任何意见都将不胜感激

编辑:

我相信我在操作中犯了一个错误。我的意思是使用和传递共享的\u ptr,而不是缓存的唯一\u ptr。当所有线程都完成缓存时,共享ptr应该删除自身

关于我的程序:我的程序是一个Web服务器,它将使用这些信息来决定返回什么信息。这是相当高的吞吐量(数千个请求/秒),每个请求查询缓存一次,因此告诉其他线程何时更新没有问题。我可以容忍稍微过时的信息,如果可能的话,我更愿意阻止所有线程执行。缓存中的信息相当大,因此我想限制任何副本的值


update\u cache
只运行一次。它在一个线程中运行,该线程只侦听更新命令并运行代码。

我觉得存在多个问题:

1) 不要泄漏内存:为此,不要在代码中使用“delete”并坚持使用unique_ptr(或在特定情况下使用shared_ptr)

2) 使用锁定(互斥)或无锁机制(std::atomic)保护对共享数据的访问

使用此签名,如果缓存中不存在该值,则必须引发异常,另一个选项是返回类似boost::optional的内容


总的来说,如果您在锁定部分之外进行代价高昂的操作(例如内存分配),您可以保持较低的延迟(一切都是相对的,我不知道您的用例)。

我觉得有多个问题:

1) 不要泄漏内存:为此,不要在代码中使用“delete”并坚持使用unique_ptr(或在特定情况下使用shared_ptr)

2) 使用锁定(互斥)或无锁机制(std::atomic)保护对共享数据的访问

使用此签名,如果缓存中不存在该值,则必须引发异常,另一个选项是返回类似boost::optional的内容


总的来说,如果您在锁定部分之外进行代价高昂的操作(例如内存分配),您可以保持较低的延迟(一切都是相对的,我不知道您的用例)。

我觉得有多个问题:

1) 不要泄漏内存:为此,不要在代码中使用“delete”并坚持使用unique_ptr(或在特定情况下使用shared_ptr)

2) 使用锁定(互斥)或无锁机制(std::atomic)保护对共享数据的访问

使用此签名,如果缓存中不存在该值,则必须引发异常,另一个选项是返回类似boost::optional的内容


总的来说,如果您在锁定部分之外进行代价高昂的操作(例如内存分配),您可以保持较低的延迟(一切都是相对的,我不知道您的用例)。

我觉得有多个问题:

1) 不要泄漏内存:为此,不要在代码中使用“delete”并坚持使用unique_ptr(或在特定情况下使用shared_ptr)

2) 使用锁定(互斥)或无锁机制(std::atomic)保护对共享数据的访问

使用此签名,如果缓存中不存在该值,则必须引发异常,另一个选项是返回类似boost::optional的内容


总的来说,如果您在锁定部分之外进行代价高昂的操作(例如内存分配),您可以保持较低的延迟(一切都是相对的,我不知道您的用例)。

shared\u ptr
对于这一目的非常合理,C++11已经做到了。如果数据在创建后是不可变的,您甚至不需要任何额外的同步:

class cache {
public:
    using map_t = std::map<std::string, value>;
    void update_cache();
    std::shared_ptr<const map_t> get_cache() const;
private:
    std::shared_ptr<const map_t> cache_;
};

void cache::update_cache()
{
    while(true)
    {
        if(recv() == "update")
        {
            auto new_info = std::make_shared<map_t>();
            // Get new info, store in new_info
            // Make immutable & publish
            std::atomic_store(&cache_,
                              std::shared_ptr<const map_t>{std::move(new_info)});
        }
    }
}

auto cache::get_cache() const -> std::shared_ptr<const map_t> {
    return std::atomic_load(&cache_);
}
类缓存{
公众:
使用map\u t=std::map;
无效更新_缓存();
std::shared_ptr get_cache()常量;
私人:
std::共享的ptr缓存;
};
void cache::update_cache()
{
while(true)
{
如果(recv()=“更新”)
{
自动新建_info=std::使_共享();
//获取新信息,存储在新信息中
//使不可变&发布
标准::原子存储和缓存,
std::shared_ptr{std::move(new_info)});
}
}
}
自动缓存::获取缓存()常量->标准::共享缓存{
返回std::原子加载(&cache);
}

共享\u ptr
对于这一目的非常合理
    void update_cache(std::unique_ptr<Map> new_info)
    {
        { // This inner brace is not useless, we don't need to keep the lock during deletion
           std::lock_guard<std::mutex> lock{m_cacheLock};
           using std::swap;
           swap(m_cache, new_cache);
        }
    }
    value get(const std::string &key)
    {
        // lock, fetch, and return. 
        // Depending on value type, you might want to allocate memory
        // before locking
    }
class cache {
public:
    using map_t = std::map<std::string, value>;
    void update_cache();
    std::shared_ptr<const map_t> get_cache() const;
private:
    std::shared_ptr<const map_t> cache_;
};

void cache::update_cache()
{
    while(true)
    {
        if(recv() == "update")
        {
            auto new_info = std::make_shared<map_t>();
            // Get new info, store in new_info
            // Make immutable & publish
            std::atomic_store(&cache_,
                              std::shared_ptr<const map_t>{std::move(new_info)});
        }
    }
}

auto cache::get_cache() const -> std::shared_ptr<const map_t> {
    return std::atomic_load(&cache_);
}