Вот сценарий:
1) используя unordered_map<int, vector<MyClass*>*>
скажем, я добавляю ключи 1, 2, … 8
2) все ключи задаются вектором при инициализации программы и больше ничего не добавляется и не удаляется
3) У меня есть 8 потоков, где поток 1 обращается к ключу [1], поток 2 обращается к ключу [2], … поток 8 обращается к ключу [8] (то есть номер потока может получить доступ только к этому номеру ключа, но не к другому ключу)
Иногда я переназначаю значение вектора * другой выделенной куче коллекции. (т. е. резьба 1 выполняет key[1] = new vector<MyClass*>
)
Я считаю, что это будет потокобезопасным, я прав? Если нет, я полагаю, я буду использовать concurrent_unordered_map.
Благодарю.
Ответ на этот вопрос можно найти в [res.on.data.races]/3
:
Стандартная библиотечная функция C ++ не должна прямо или косвенно изменять объекты (1.10), доступные для потоков, отличных от текущего потока, если к объектам не осуществляется прямой или косвенный доступ через неконстантные аргументы функции, включая this.
Более того, [container.requirements.dataraces]/1
состояния:
В целях избежания гонок данных (
[res.on.data.races]
), реализации должны учитывать следующие функцииconst
:begin
,end
,rbegin
,rend
,front
,back
,data
,find
,lower_bound
,upper_bound
,equal_range
,at
и, за исключением ассоциативных или неупорядоченных ассоциативных контейнеров,operator[]
,
поскольку unordered_map :: Оператор [] является неконстантным, для реализации законно изменить unordered_map
когда звонок operator[]
происходит. Вы должны вместо этого использовать unordered_map :: найти, который явно должен рассматриваться как const
и, следовательно, не будет изменять unordered_map
:
map.find(key)->second = new vector<MyClass*>;
(Как примечание, ваш предложенный дизайн выглядит как рецепт для утечек памяти. Почему бы не сделать это unordered_map<int, std::unique_ptr<vector<MyClass*>>>
, или же unordered_map<int,vector<MyClass*>>
?)
Других решений пока нет …