2009-12-04 2 views
17

У меня есть 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 = ""; 
} 

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

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

Обновление: Отредактированный образец кода для константной корректности.

ответ

16

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

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

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

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

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

+1

Примечания: Ответ ограничиваются SGI STL реализации внешним. ОП не упоминает, какой из них используется. – foraidt

+0

Верно, я отредактирую, чтобы добавить эту информацию. – laura

+0

Я использую реализацию, которая поставляется с visual studio 2008, но я искал ответ, который охватывает std :: map в целом или, по крайней мере, для большинства реализаций, если это вообще возможно. –

9

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

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

+0

Я бы рассмотрел реализацию с изменчивой небезопасной внутренней внутренней ошибкой. – hirschhornsalz

+0

Я немного обновил свой код, чтобы использовать константную ссылку на карту, и const_iterator –

+0

drhirsch, не-поточная реализация может по-прежнему соответствовать стандартам, но она, безусловно, будет некачественной. – Useless