Безопасна ли только запись в общий поток std::unordered_map?

Скажем, у меня есть инициализированный, но пустой std::unordered_map и два одновременных потока, которые будут его заполнять. Два потока будут только записывать на карту, и ничего не будет считываться с карты, пока два потока не закончат работу.

Кроме того, два потока никогда не будут работать с одними и теми же ключами на карте. Например, скажем, поток 1 будет заполнять ключи от «A» до «M», а поток 2 будет одновременно заполнять ключи от «N» до «Z».

Эта ветка безопасна?

В моей текущей реализации у меня есть 8 потоков, записывающих в один мьютексированный std::unordered_map способом, описанным выше. Мьютекс явно замедляет процесс (заполняется около 10 000 ключей), поэтому мне интересно, нужен ли мне вообще мьютекс.

Спасибо всем!

Я видел похожие вопросы. Если важна производительность, рассмотрите другую структуру данных. Возможно, иметь unordered_map для каждого потока было бы лучше, если бы они не пересекались по ключам.

Dan M. 31.01.2019 17:58

Почитайте std::unordered_map::merge. Два потока могут заполнить две разные карты, а затем их можно объединить.

Öö Tiib 31.01.2019 18:09

@ÖöTiib Для этого требуется C++17. Q помечен как C++11

NathanOliver 31.01.2019 18:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
285
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нет, это не потокобезопасно. Класс std::unordered_map не предоставляет никаких специальных гарантий потокобезопасности, только тот же самый обычный уровень потокобезопасности, который по умолчанию обеспечивают все стандартные классы. Это означает, что для одного потока небезопасно каким-либо образом обращаться к структуре, в то время как другой поток изменяет или может изменять ее.

IRC, существуют некоторые дополнительные гарантии для классов std в отношении методов const, но в данном случае они не актуальны. Один простой способ, которым это может сломаться, - это если вставка нового значения вызывает перехеширование, в то время как другой поток находится в середине вставки другого значения.

Dan M. 31.01.2019 17:56

@ДэнМ. Все функции const являются считывателями, так что все в порядке, если это все, что вы делаете. Как только вы добавите писателя в микс, все ставки сняты

NathanOliver 31.01.2019 17:58

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

David Schwartz 31.01.2019 18:00

@ Натан Оливер, нет, не совсем. Функции const могут все. Нет никакой гарантии, что они будут потокобезопасными. Но STL предоставляет такую ​​гарантию.

Dan M. 31.01.2019 18:03

@ДэнМ. Я имел в виду в контексте STL.

NathanOliver 31.01.2019 18:04

@DavidSchwartz Я не предполагаю. Я утверждаю это как реальный сценарий, демонстрирующий, как он нарушает потокобезопасность, даже если «все потоки действуют на разные ключи», чтобы подчеркнуть, что это не потокобезопасно.

Dan M. 31.01.2019 18:07

@ДэнМ. Но проблема в том, что если у ОП есть другой (но похожий) вопрос, а затем он делает вывод: «Я не понимаю, как это может пойти не так; это должно быть безопасно», они будут введены в заблуждение.

Martin Bonner supports Monica 31.01.2019 18:46

@MartinBonner чем введен в заблуждение? «Нет, это небезопасно. Вот один из многих способов, которыми он может сломаться» как вводит в заблуждение? Я бы сказал, что без этого примера OP может быть введен в заблуждение (и уже почти был) «Но у меня есть очень конкретные варианты использования, которые наверняка будут потокобезопасными!», Нет, это не так, и вот почему.

Dan M. 31.01.2019 18:51

@ДэнМ. Это прекрасный пример того, как можно ввести человека в заблуждение. То, что вы можете придумать, как это может привести к сбою, - это НЕТ, почему его очень конкретный вариант использования не является потокобезопасным. Его очень специфический вариант использования не является потокобезопасным, поскольку об этом говорится в соответствующих стандартах. Даже случаи, когда никто не может придумать, как это может привести к сбою, не являются потокобезопасными. К сожалению, это очень распространенное заблуждение, которое на протяжении многих лет приводило к огромному количеству боли и страданий.

David Schwartz 31.01.2019 19:16

Я не могу сказать вам, сколько раз, обычно в комментариях на этом самом веб-сайте, люди утверждали, что все безопасно, а я настаивал, что это не так. Затем кто-то (иногда я, а что-то иное) объяснил, как он может выйти из строя, и они сказали: «О, теперь понятно. Это небезопасно». Это худший возможный урок, который они могут усвоить, настраивая их на провал, как только они полагаются на что-то, режимы отказа которых они недостаточно умны, чтобы предвидеть. Черт возьми, когда-то мысль о том, что ЦП будет выполнять запись вне порядка программы, была непредвиденной.

David Schwartz 31.01.2019 19:18

Вот почему я хотел спросить вместо локального тестирования ... не уверен, что мои простые тесты будут A) работать единогласно и B) масштабироваться до моей полной реализации. Учитывая всю эту информацию, я просто оставлю мьютекс. Спасибо всем!

pcdangio 31.01.2019 20:20

@DavidSchwartz, вот что я сказал. Я никогда не оспаривал конкретный вариант использования, я добавил к исходному вопросу более подробное объяснение. Потому что исходный вопрос был построен так. Является ли потокобезопасным? Нет. Даже если я сделаю только Б? Да, даже если вы делаете только Б, вот почему. Ваша логика в конечном счете ошибочна. Я мог бы утверждать то же самое: поскольку пользователь будет получать только ответы «да/нет» без каких-либо объяснений, он никогда не научится думать/предвидеть себя. С другой стороны, очень важна способность оспаривать их идеи и быстро находить контрпримеры.

Dan M. 31.01.2019 20:34

@ДэнМ. Чего вы, кажется, не понимаете, так это того, что этот особый навык предвидения для себя не только бесполезен, но и определенно вреден. В большинстве случаев вы можете предвидеть, как он может сломаться. Но это так же неправильно, даже когда вы не можете предвидеть, как он может сломаться, на самом деле, тогда это гораздо вреднее. Таким образом, развитие навыка видеть, как он может сломаться, вводит вас в заблуждение и заставляет думать, что в менее распространенном случае, когда вы не можете предвидеть, как он может сломаться, вы в безопасности. Вот почему я упорно работаю над тем, чтобы не склонять людей к такому образу мышления. Это приводит только к ошибкам.

David Schwartz 28.12.2019 20:52

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