Подтвердить что ты не робот

Защита потоков std:: map для операций только для чтения

У меня есть 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.

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

4b9b3361

Ответ 1

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

Вот ссылка: http://www.sgi.com/tech/stl/thread_safety.html

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

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

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

Ответ 2

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

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