Какие операции являются потокобезопасными на std::map?

Предположим, у меня есть:

stl::map<std::string, Foo> myMap;

безопасна ли следующая функция потока?

myMap["xyz"] ?

Т.е. я хочу иметь эту гигантскую карту только для чтения, которая используется многими потоками; но я не знаю, если даже поиск это потокобезопасно.


Все написано в первый раз.

Затем, после этого, несколько потоков читают из него.

Я пытаюсь избежать блокировок, чтобы сделать это как можно быстрее. (яя возможна преждевременная оптимизация, я знаю)

6 ответов

Решение

Теоретически, контейнеры STL не являются потокобезопасными. На практике чтение безопасно, если контейнер не изменяется одновременно. то есть стандарт не содержит спецификаций о потоках. Следующая версия стандарта и IIUC гарантируют безопасное поведение только для чтения.

Если вы действительно обеспокоены, используйте отсортированный массив с двоичным поиском.

C++11 требует, чтобы все функции-члены были объявлены как const Потокобезопасны для нескольких читателей.

призвание myMap["xyz"] не является потокобезопасным, так как std::map::operator[] не объявлен как const, призвание myMap.at("xyz") хотя потокобезопасен, так как std::map::at объявлен как const,

По крайней мере, в реализации Microsoft чтение из контейнеров является поточно- ориентированным ( ссылка).

Тем не мение, std::map::operator[] может изменять данные и не объявляется const, Вы должны вместо этого использовать std::map::find, который const, чтобы получить const_iterator и разыменовывать это.

Теоретически, структуры данных и функции только для чтения не требуют каких-либо блокировок для обеспечения безопасности потоков. Это по своей сути потокобезопасно. При одновременном чтении из памяти не происходит скачек данных. Однако вы должны гарантировать безопасную инициализацию только одним потоком.

Как отметил Макс С., в основном реализация чтения элемента в карте похожа на myMap["xyz"] не будет иметь операций записи. Если так, то это безопасно. Но, опять же, вы должны гарантировать, что нет потока, который изменяет структуру, кроме фазы инициализации.

Коллекции STL не являются поточно-ориентированными, но добавить в них безопасность потоков довольно просто.

Лучше всего создать потоковую оболочку вокруг рассматриваемой коллекции.

Это старый вопрос, но поскольку все существующие ответы, и в частности принятый, неверны, я добавляю еще один (извините, недостаточно представителей для комментариев).

Поскольку в OP явно упоминается доступ только для чтения (_ «гигантская карта только для чтения»), на самом деле не следует использовать, так как это может привести к вставке. Методы или являются подходящими альтернативами.

Некоторые неконстантные функции рассматриваются в контексте потокобезопасности. а также являются такими псевдоконстантными функциями (это очень хорошо объясняется в другом вопросе . Более подробная информация доступна на сайте cppreference.com , а также в разделе «потокобезопасность». И, наконец, см. стандарт С++11 23.2.2.1 для официального список).

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

Другие вопросы по тегам