Стандарт C ++ дает определенные гарантии многопоточности для всех классов в стандартной библиотеке C ++. Эти гарантии могут быть не такими, как вы ожидаете, но для всех стандартных классов библиотеки C ++ сделаны определенные гарантии безопасности потоков. Убедитесь, что вы прочитали предоставленные гарантии, поскольку гарантии потоков в стандартных контейнерах C ++ обычно не совпадают с желаемыми. Для некоторых классов разные, как правило, более строгие гарантии, и ответ ниже конкретно относится к контейнерам. Контейнеры по существу имеют следующие гарантии безопасности потока:
- может быть несколько одновременных считывателей одного контейнера
- если есть один писатель, больше не будет писателей и читателей
Как правило, это не то, что люди хотели бы в качестве гарантии безопасности потоков, но они очень разумны, учитывая интерфейс стандартных контейнеров: они предназначены для эффективного использования при отсутствии нескольких потоков доступа. Добавление любого вида блокировки для их методов может помешать этому. Кроме того, интерфейс контейнеров не очень полезен для любой формы внутренней блокировки: обычно используется несколько методов, и доступ зависит от результата предыдущих доступов. Например, после проверки того, что контейнер не empty()
, можно получить доступ к элементу. Однако при внутренней блокировке нет гарантии, что объект все еще находится в контейнере, когда к нему фактически осуществляется доступ.
Чтобы соответствовать требованиям, которые дают вышеупомянутые гарантии, вам, вероятно, придется использовать некоторую форму внешней блокировки для одновременно доступных контейнеров. Я не знаю о буст-контейнерах, но если они имеют интерфейс, аналогичный интерфейсу стандартных контейнеров, я подозреваю, что они имеют точно такие же гарантии.
Гарантии и требования приведены в пункте 17.6.4.10 [res.on.objects]:
Поведение программы не определено, если вызовы стандартных библиотечных функций из разных потоков могут привести к гонке данных. Условия, при которых это может произойти, указаны в 17.6.5.9. [Примечание: изменение объекта стандартного типа библиотеки, который используется совместно между потоками, может привести к неопределенному поведению, если только объекты этого типа явно не определены как разделяемые без гонок данных или пользователь не предоставит механизм блокировки. -endnote]
... и 17.6.5.9 [res.on.data.races]. Этот раздел по существу детализирует более неформальное описание в статье.