безопасность потока unordered_map - PullRequest
22 голосов
/ 13 марта 2012

Я изменяю однопотоковую программу на многопоточность, используя библиотеку boost: thread. Программа использует unordered_map в качестве hasp_map для поиска. Мой вопрос ..

В одно время многие потоки будут писать, а в другое время многие будут читать, но не одновременно и читать, и писать, то есть либо все потоки будут читать, либо все будут писать. Будет ли это потокобезопасным и контейнер предназначен для этого? И если это будет так, будет ли это одновременно и улучшать производительность? Нужно ли использовать какой-нибудь механизм блокировки?

Я где-то читал, что Стандарт C ++ говорит, что поведение будет неопределенным, но это все?

ОБНОВЛЕНИЕ: Я также думал о Intel concurrent_hash_map. Это будет хороший вариант?

Ответы [ 5 ]

45 голосов
/ 13 марта 2012

Контейнеры STL разработаны таким образом, чтобы вы могли иметь:

A. Одновременное чтение нескольких потоков

или

B. Один поток пишет одновременно

Запись в несколько потоков не является одним из указанных выше условий и не допускается. Таким образом, запись в несколько потоков приведет к гонке данных, поведение которой не определено.

Вы можете использовать мьютекс, чтобы это исправить. Shared_mutex (в сочетании с shared_locks) был бы особенно полезен, так как этот тип мьютекса допускает множественное одновременное чтение.

http://eel.is/c++draft/res.on.data.races#3 является частью стандарта, которая гарантирует возможность одновременного использования функций const в разных потоках. http://eel.is/c++draft/container.requirements.dataraces определяет некоторые дополнительные неконстантные операции, которые безопасны в разных потоках.

8 голосов
/ 13 марта 2012

Будет ли это потокобезопасным и предназначен ли контейнер для этого?

Нет, стандартные контейнеры не являются поточно-безопасными.

Нужно ли использовать какой-нибудь механизм блокировки?

Да, вы делаете. Поскольку вы используете boost, boost::mutex будет хорошей идеей; в C ++ 11 есть std::mutex.

Я где-то читал, что Стандарт C ++ говорит, что поведение будет неопределенным, но это все?

Действительно, поведение не определено. Я не уверен, что вы подразумеваете под «это все?», Поскольку неопределенное поведение - это наихудший из возможных вариантов поведения, и программа, которая его демонстрирует, по определению неверна. В частности, неправильная синхронизация потоков может привести к случайным сбоям и повреждению данных, часто очень сложными для диагностики способами, поэтому было бы разумно избежать этого любой ценой.

ОБНОВЛЕНИЕ: я также думал о Intel concurrent_hash_map. Это будет хороший вариант?

Звучит хорошо, но я никогда не использовал его сам, поэтому не могу высказать свое мнение.

3 голосов
/ 30 января 2017

std :: unordered_map соответствует требованиям Контейнера (ref http://en.cppreference.com/w/cpp/container/unordered_map). Для обеспечения безопасности контейнерной резьбы см .: http://en.cppreference.com/w/cpp/container#Thread_safety.

Важные моменты:

  • "Различные элементыв одном и том же контейнере могут быть изменены одновременно разными потоками "
  • " Все функции-члены const могут вызываться одновременно разными потоками в одном и том же контейнере. Кроме того, функции-члены begin (), end (), rbegin(), rend (), front (), back (), data (), find (), lower_bound (), upper_bound (), equal_range (), at () и, кроме ассоциативных контейнеров, оператор [],ведут себя как const в целях обеспечения безопасности потоков (то есть они могут также вызываться одновременно разными потоками в одном и том же контейнере). "
3 голосов
/ 13 марта 2012

Существующие ответы охватывают основные моменты:

  • у вас должна быть блокировка для чтения или записи на карту
  • вы можете использовать блокировку на несколько читателей / на одну записьдля улучшения параллелизма

Кроме того, вы должны знать, что:

  • с использованием ранее полученного итератора или ссылки или указателя на элемент на карте, считается как операция чтения или записи

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

1 голос
/ 13 марта 2012

Вы можете использовать concurrent_hash_map или использовать мьютекс при доступе к unordered_map.одна из проблем при использовании intel concurrent_hash_map заключается в том, что вам нужно включить TBB, но вы уже используете boost.thread.Эти два компонента имеют перекрывающуюся функциональность и, следовательно, усложняют вашу кодовую базу.

...