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 говорит, что никакой другой поток не будет конфликтовать с записями в этот элемент при изменении карты. (Спасибо Якку за последний кусок головоломки)

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