Потоковая безопасность std :: map для операций только для чтения - PullRequest
17 голосов
/ 04 декабря 2009

У меня есть std :: map, который я использую для сопоставления значений (идентификаторов полей) с удобочитаемой строкой. Эта карта инициализируется один раз, когда моя программа запускается до запуска любых других потоков, и после этого она никогда не изменяется снова. Прямо сейчас я даю каждому потоку свою копию этой (довольно большой) карты, но это явно неэффективное использование памяти и замедляет запуск программы. Поэтому я думал дать каждому потоку указатель на карту, но это поднимает проблему безопасности потока.

Если все, что я делаю, это чтение с карты, используя следующий код:

std::string name;
//here N is the field id for which I want the human readable name
unsigned field_id = N; 
std::map<unsigned,std::string>::const_iterator map_it;

// fields_p is a const std::map<unsigned, std::string>* to the map concerned.
// multiple threads will share this.
map_it = fields_p->find(field_id);
if (map_it != fields_p->end())
{
    name = map_it->second;
}
else
{
    name = "";
}

Будет ли это работать или есть проблемы с чтением std :: map из нескольких потоков?

Примечание. В настоящее время я работаю с Visual Studio 2008, но мне бы хотелось, чтобы это работало в большинстве основных реализаций STL.

Обновление: отредактированный пример кода для правильности констант.

Ответы [ 3 ]

16 голосов
/ 04 декабря 2009

Это будет работать из нескольких потоков, пока ваша карта остается прежней. Карта, которую вы используете, является де-факто неизменной, поэтому любая находка на самом деле сделает находку на карте без изменений.

Вот соответствующая ссылка: http://www.sgi.com/tech/stl/thread_safety.html

Реализация SGI STL потокобезопасен только в том смысле, что одновременный доступ к отчетливым контейнеры безопасны и одновременны чтение доступа к общим контейнерам безопасны Если несколько потоков обращаются к один контейнер и хотя бы один Поток может потенциально написать, тогда Пользователь несет ответственность за обеспечение взаимное исключение между потоками во время доступа к контейнеру.

Вы попадаете в категорию "одновременный доступ для чтения к совместно используемым контейнерам".

Примечание: это верно для реализации SGI. Вам нужно проверить, используете ли вы другую реализацию. Насколько мне известно, из двух реализаций, которые широко используются в качестве альтернативы, STLPort имеет встроенную безопасность потоков. Я не знаю о реализации Apache, хотя.

9 голосов
/ 04 декабря 2009

Все должно быть в порядке. Вы можете использовать const ссылки на него, если хотите документировать / применять поведение только для чтения.

Обратите внимание, что корректность не гарантируется (в принципе, карта может выбрать балансировку при вызове find), даже если вы используете только методы const (действительно неверная реализация может объявить изменяемое дерево). Однако на практике это кажется маловероятным.

3 голосов
/ 04 декабря 2009

Да, это так.

Смотрите похожие сообщения с тем же вопросом о std :: set:

Является ли C ++ std :: set поточно-безопасным?

...