Потокобезопасность контейнеров std C++

Я читал много постов здесь с вопросом, если стандартные контейнеры для C++ (как "список" или "карта" являются потокобезопасными и все они сказали, что это не в целом. Параллельные чтения должны быть в порядке, но параллельные записи или параллельные чтения и записи могут вызвать проблемы.

теперь я узнал, что в www.cplusplus.com этот доступ или изменение списка во время большинства операций является безопасным.

некоторые примеры:

карте::найти

доступ к контейнеру (ни const, ни версии без const не изменяют контейнер). Доступ к сопоставленным значениям не осуществляется: одновременный доступ к элементам или их изменение безопасны.

map:: insert

контейнер изменен. Одновременный доступ к существующим элементам безопасен, хотя итерация диапазонов в контейнере-нет.

Я не понимаю cplusplus.com или там что-нибудь еще, что я должен знать о безопасности потоков в контейнерах std.

спасибо заранее!

PS: Я прошу C++03, а не C++11

4 ответов


звучит правильно.

обратите внимание, что доступ к значениям внутри map из нескольких потоков, если вы измените фактическое значение, также необходимо будет защитить. Если вы знаете, что два потока обновляют разные записи (я не имею в виду вставку/удаление), то это безопасно.


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

это правильно. Это гарантия, предлагаемая в целом для несинхронизированного доступа к объектам в C++. Такие "проблемы" формально называются гонки данных.

теперь я узнал, что на www.cplusplus.com этот доступ или изменение списка во время большинства операций является безопасным.

нет, контейнеры не предлагайте больше, чем базовая гарантия для concurrent читает. Будет гонка данных, если один поток обращается к нему, а другой изменяет его. Однако с некоторыми контейнерами иногда безопасно получить доступ элементов контейнера, в то время как сам контейнер изменяется.

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

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

Я прошу C++ , а не C++11

в наши дни, C++ is C++11. Если вы спрашиваете об исторических версиях языка, они ничего не сказать о потоках, поэтому вопрос не отвечает в целом, только для конкретной реализации и структуры потоков.


до C++11 в стандарте не было понятия "поток". Таким образом, вопрос о том, является ли контейнер потокобезопасным, бессмыслен в контексте C++03.


Как отметил Марсин, C++03 не имеет понятия потока; следовательно, вы не можете предположить какую-либо потокобезопасную операцию даже для одновременного чтения в двух потоках после записи, которая полностью завершена.

подумайте об этом случае: При t=0 вы создаете поток, назовем При t=10 сек поток B (который существует до создания потока A) записывается в контейнер. При t=1 часе поток A и B оба пытаются прочитать контейнер без какой-либо синхронизации через стороннюю библиотеку (например, pthread в).

C++03 гарантирует только, что поток B увидит правильное значение. Но нет никакой гарантии, что поток A увидит правильное значение, потому что C++03 ожидает, что каждая программа является одним потоком, и поэтому спецификация C++03 может гарантировать только последовательность событий, видимых в запрограммированном порядке (как если бы в 1 потоке).