【发布时间】:2015-02-23 20:26:06
【问题描述】:
我的一个程序中有一个缓存系统。我有一个单独的静态类来维护这个缓存,并在多个线程中同时使用缓存。我遇到了正确维护缓存系统的问题。这是一些示例代码。
class db_cache
{
public:
typdef std::map<int, int> map_t;
static void update_cache();
static boost::shared_ptr< const map_t > get_cache();
private:
db_cache();
static void run_update();
static boost::shared_ptr< const map_t > cur_cache_;
static boost::shared_ptr< const map_t > old_cache_;
};
void db_cache::update_cache()
{
cur_cache_ = boost::make_shared< map_t >();
old_cache_ = boost::make_sahred< map_t >();
//
//Setup connection to server that sends updates
//
//Initialize cache
run_update();
while(true)
{
if(recv().compare("update") == 0)
{
//Update cache if update message recieved
run_update();
}
}
}
void db_cache::run_update()
{
//Create new cache to swap with current cache
auto new_cache = boost:make_shared<map_t>();
//
//Put data in new cache
//
boost::atomic_store(&old_cache_, boost::move(cur_cache_));
boost::atomic_store(&cur_cache_, boost::shared_ptr< const map_t >(boost::move(new_cache)));
}
auto db_cache::get_cache() -> boost::shared_ptr< const map_t >
{
return boost::atomic_load(&cur_cache_);
}
我目前在boost::atomic_store(&old_cache_, boost::move(cur_cache_)); 遇到崩溃。崩溃似乎是因为old_cache_ 为空。这似乎发生在第二次收到更新消息时。我假设正在发生的事情(不是 100% 肯定,但我能想到的唯一一种方法)是:
- 第一次收到消息时,
cur_cache_被复制到old_cache_。 -
cur_cache_被new_cache替换,导致旧的cur_cache_(old_cache_当前也指向)为空。 -
old_cache_由于为空而再次调用boost::atomic_store时会导致崩溃。
我的问题是,为什么boost::atomic_store(&old_cache_, boost::move(cur_cache_)); 不会导致cur_cache_ 的引用计数器增加。有什么办法可以实现吗?
其他说明:
我有old_cache_ 的原因是因为我相信我在从缓存中读取时遇到了问题,这很可能也是一个问题。在尝试从get_cache() 返回的映射中读取元素时,我的程序似乎崩溃了,因此为了确保它们保持在范围内,直到当前具有副本的所有线程都完成,我保存了缓存的最后一个版本。我想如果我有正确的方法来做到这一点,我可以一起摆脱old_cache_,这应该可以解决上述问题。
编辑:
这里是使用缓存的代码:
//Vector big, don't want to copy
const std::vector *selected_vec = &(*db_cache::get_cache()).at(get_string);
for( std::vector<std::string>::iterator it = selected_vec->begin(), e = selected_vec->end(); it != e; ++it)
{
//String can be big, don't want to copy
const std::string *cur_string = &(*it);
if(cur_string == nullptr || cur_string->size() == 0)
{
continue;
}
char a = cur_string->at(0); //Crash here
//Do Stuff
}
我的实际 map_t 类型是 std::map<std::string,std::vector<std::string>> 类型而不是 std::map<int,int>。在调用get_cache() 之后,我得到了我想要的向量,以及向量上的迭代器。对于每个字符串,我尝试获取第一个字符。当我尝试获取字符时,程序崩溃了。我唯一能想到的就是selected_vec被删除了。
【问题讨论】:
标签: c++ multithreading caching boost shared-ptr