以相对简单的形式考虑一个线程安全的 getter 方法:
std::map<std::string, boost::shared_ptr<AAA> > repo;
AAA & get(const std::string &key)
{
boost::upgrade_lock<boost::shared_mutex> lock(repoMutex);
std::map<std::string, boost::shared_ptr<AAA> >::iterator it = repo.find(key);
if(it == repo.end()){
boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
boost::shared_ptr<AAA> t(new AAA(key));
repo.insert(std::make_pair(key,t));
return *t;
}
return *it->second;
}
在上面,我使用共享(可升级)锁来保护查找操作,并且仅当我需要插入键/值时才升级到唯一锁。到目前为止,一切都很好?
我想象的是以下(如果我的概念在任何步骤中是错误的,请告诉我):
两个线程进入方法
两者都允许同时运行
repo.find()
同一个密钥(并且该密钥不存在)。他们都失败了。因为密钥不存在。
第一个线程通过进入升级区域获得独占访问,而第二个线程等待进入升级区域。
第一个线程完成为 key 创建新条目的工作,然后离开。
第二个线程进入并覆盖第一个线程插入的键/值。(这不是任何人想要的)
我们如何解决这个问题?谢谢