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

Unordered_map безопасность потоков

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

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

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

UPDATE: Я также думал о Intel concurrent_hash_map. Будет ли это хорошим вариантом?

4b9b3361

Ответ 1

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

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

или

В. Один поток, записывающий в то же время

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

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

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

Ответ 2

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

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

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

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

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

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

UPDATE: Я также думал о Intel concurrent_hash_map. Будет ли это хорошим вариантом?

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

Ответ 3

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

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

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

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

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

Ответ 4

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

Ответ 5

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

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

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