std::map потокобезопасность
Является ли ссылка на объект в std::map потокобезопасной?
std::map< std::string, Object > _objects;
Карта может быть изменена из многих потоков, и этот доступ синхронизирован, но ссылка на значение (Object &) доступна только из 1 экземпляра и потока. безопасны ли операции записи с Object и если другой поток добавит элементы на карту? это перераспределит?
2 ответа
Стандарт C++11 гарантирует, что const
метод доступа к контейнерам безопасен из разных потоков (т.е. оба используют const
методы).
Кроме того, [container.requirements.dataraces] сообщает
Реализации требуются, чтобы избежать гонок данных, когда содержимое содержащегося объекта в разных элементах в одной и той же последовательности, за исключением
vector<bool>
Другими словами, кроме vector<bool>
изменение различного содержимого не является гонкой данных.
Теперь, если один поток делает недействительным итератор, используемый другим потоком, очевидно, что это гонка данных (и приводит к неопределенному поведению). Если один поток неconst
доступ к контейнеру, а другой делает const
доступ, то есть гонка данных (и неопределенное поведение). (Примечание: ряд функций "считается const
"с целью многопоточности, в том числе begin
, end
и другие функции (и методы), которые не являютсяconst
просто потому, что они возвращают неconst
итераторы. []
входит в этот набор псевдо-const
по соображениям безопасности нитей, кроме map
а также unordered_set
и т. д. - 23.2.2.1).
Однако, похоже, что если у вас есть ссылка на элемент в контейнере, и вы участвуете в операциях, которые не делают эту ссылку недействительной в другом потоке и никогда не записывают этот элемент в другом потоке, вы можете безопасно прочитать эту ссылку. Точно так же, если другие потоки никогда даже не читают из элемента, то запись в этот элемент не должна приводить к неопределенному поведению.
Что касается ссылок на стандарты, 17.6.5.9.5, кажется, гарантирует, что функции из стандартной библиотеки не будут убегать и без необходимости читать / записывать элементы.
Итак, краткий ответ: вы в безопасности, если другой поток напрямую не связывается с этой конкретной записью в map
,
Элементы на карте стабильны, они не перемещаются и не становятся недействительными, если элемент не удален с карты. Если только один поток пишет в данный объект, и изменения в самой карте правильно синхронизированы, то я считаю, что это будет безопасно. Я уверен, что это безопасно на практике, и я думаю, что это безопасно и в теории.
Стандарт гарантирует, что различные элементы могут быть изменены различными потоками, в [container.requirements.dataraces]
Несмотря на (17.6.5.9), реализации должны избегать гонок данных, когда содержимое содержащегося объекта в разных элементах в одной и той же последовательности, за исключением
vector<bool>
, изменяются одновременно.
Это позволяет только изменять элементы, а не вставлять новые элементы в карту при изменении элементов. Для некоторых контейнеров, таких как std::vector
изменение самого вектора может также изменять элементы путем их перераспределения и перемещения, но [associative.reqmts]/9 обеспечивает std::map
не сделает недействительными существующие элементы.
Так как нет функции-члена std::map
требуется для доступа ко второму элементу его элементов (т.е. mapped_type
Я думаю, что [res.on.data.races]/5 говорит, что никакой другой поток не будет конфликтовать с записями в этот элемент при изменении карты. (Спасибо Якку за последний кусок головоломки)