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

Std:: map thread-safety

Ссылка на объект в std:: map является потокобезопасной?

std::map< std::string, Object >   _objects;
Карта

может быть изменена из многих потоков, и этот доступ синхронизирован, но ссылка на значение (Object &) доступна только из 1 экземпляра и потока. является ли операция записи с объектом и безопасна, если другой поток добавит элементы для отображения? перераспределит ли он?

4b9b3361

Ответ 1

Стандарт С++ 11 гарантирует, что метод const доступа к контейнерам безопасен из разных потоков (т.е. используют методы const).

Кроме того, [container.requirements.dataraces] указывает

чтобы избежать сбоев данных, когда содержимое содержащий объект в разных элементах в той же последовательности, кроме vector<bool>

Другими словами, кроме vector<bool>, изменяющего различное содержимое, это не гонка данных.

Теперь, если один поток аннулирует итератор, используемый другим потоком, очевидно, что это гонка данных (и приводит к поведению undefined). Если один поток не поддерживает const доступ к контейнеру, а другой имеет доступ const, то есть гонку данных (и поведение undefined). (Примечание: ряд функций "считается const" для многопоточности, включая begin, end и другие функции (и методы), которые не являются const, просто потому, что они возвращают не const iterators. [] включен в этот набор псевдо-const для причин безопасности потока, за исключением map и unordered_set и т.д. - 23.2.2.1).

Однако, похоже, что если у вас есть ссылка на элемент внутри контейнера и включайте операции, которые не делают недействительной эта ссылка в другом потоке и никогда не записывают этот элемент в другой поток, вы можете спокойно читать из этого Справка. Точно так же, если другие потоки никогда не читаются из этого элемента, запись в этот элемент не должна приводить к поведению undefined.

Для ссылок на стандарты, 17.6.5.9.5, похоже, гарантирует, что функции из стандартной библиотеки не будут убегать и читать/писать элементы без необходимости.

Итак, короткий ответ: вы в безопасности, если другой поток напрямую не связан с этой конкретной записью в map.

Ответ 2

Элементы на карте стабильны, они не перемещаются или недействительны, если элемент не удаляется с карты. Если на данный объект записывается только один поток, и изменения в самой карте корректно синхронизируются, то Я верю, это будет безопасно. Я уверен, что это безопасно на практике, и я думаю, что это тоже безопасно.

Стандарт гарантирует, что отдельные элементы могут быть изменены различными потоками, в [container.requirements.dataraces]

Несмотря на (17.6.5.9), для предотвращения расы данных требуется реализация, когда содержимое содержащегося объекта в разных элементах в одной и той же последовательности, за исключением vector<bool>, изменяется одновременно.

Это позволяет вам изменять элементы, а не вставлять новые элементы в карту при изменении элементов. Для некоторых контейнеров, таких как std::vector, изменение самого вектора также может изменять элементы путем перераспределения и перемещения их, но [associative.reqmts]/9 гарантирует, что std::map не приведет к аннулированию существующих элементов.

Поскольку для доступа к второму элементу его элементов (т.е. mapped_type) не требуется функция-член std::map, я думаю, [res.on.data.races]/5 говорит, что ни один другой поток не будет конфликтовать с записью в этот член при изменении карты. (Спасибо Якку за этот последний кусок головоломки)