Рассмотрят поточно-геттер в относительно, простейшей форме:путаницы с использованием обновляемого замка на станде :: Карта найдого/вставить
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()
для один и тот же ключ одновременно (и ключ не существует).Оба отказались. Ключ не существует.
первый поток получает монопольный доступ, введя модернизированную зону, в то время как второй поток, ждущий, чтобы войти модернизированную зону.
первая нить заканчивает свою работу по созданию новой записи для ключа, а затем уходит.
второй поток входит и перезаписывает ключ/значение, вставленное в первом потоке. (Это не то, что кто-то хочет)
Как решить эту проблему? спасибо
Спасибо за помощь. Кстати, как и во втором варианте, 'lower_bound' и' find' имеют логарифмическую временную сложность. то они должны принимать такое же количество времени. ? – rahman
@rahman Я забыл изменить вызов 'insert', проверьте обновление. Он принимает итератор как подсказку и в этом случае имеет O (1) амортизированную сложность (см. Таблицу 102 в стандарте, ищите 'emplace_hint'). –