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

Является ли stl-вектор одновременным чтением потокобезопасным?

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

Я ищу следующий прецедент:

  • Вектор инициализируется несколькими элементами типа std::string. (Предположим, что имя объекта - strList). strList будет инициализирован во время запуска приложения.
  • Все потоки будут перебирать по strList, чтобы увидеть, соответствует ли значение значению по крайней мере одному элементу strList.
  • Ни один нить никогда не попытается изменить strList, и он будет строго использоваться как объект readonly.

Так что, пожалуйста, скажите, если параллельные чтения являются потокобезопасными для векторного объекта. Я использую RHEL 6, а версия gcc - 4.5.x

4b9b3361

Ответ 1

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


Собственно, STL - это не правильный способ его обращения.
Это Стандартная библиотека С++.

Стандарт С++ 03 вообще не говорит о concurrency, поэтому аспект concurrency оставлен как деталь реализации для компиляторов. Поэтому документация, прилагаемая к вашему компилятору, должна искать ответы, связанные с concurrency.

Большинство реализаций STL - это не потокобезопасность как таковая.
Но для одновременного чтения одного и того же объекта из нескольких потоков большинство реализаций STL действительно являются потокобезопасными.

Литература:

MSDN говорит:

Один объект является потокобезопасным для чтения из нескольких потоков. Например, при заданном объекте A безопасно читать A из потока 1 и из потока 2 одновременно.

Документация STL-документации Dinkumware гласит:

Несколько потоков могут безопасно читать один и тот же объект-контейнер. (В объекте-контейнере есть связанные с nunprotected изменчивые подобъекты.)

Документация GCC говорит:

В настоящее время мы используем определение безопасности потока SGI STL, в котором говорится:

SGI-реализация STL является потокобезопасной только в том смысле, что одновременный доступ к отдельным контейнерам безопасен, а одновременный доступ к доступу к общим контейнерам безопасен. Если несколько потоков обращаются к одному контейнеру, и, по крайней мере, один поток может потенциально писать, тогда пользователь отвечает за обеспечение взаимного исключения между потоками во время доступа к контейнеру.

Итак, из приведенного выше, Да, поточно-безопасный в GCC имеет одновременное чтение одного и того же объекта из нескольких потоков.

Примечание. Стандартная библиотека GCC является производной кода SGI STL.

Ответ 2

Для этого есть специальное упоминание в С++ 0x FDIS (n3290).

§ 17.6.5.9 Уклонение от гонки данных

Весь параграф представляет интерес, но более конкретно:

3/Стандартная библиотечная функция С++ не должна прямо или косвенно изменять объекты (1.10), доступные для потоков, отличных от текущего потока, если только объекты не получают прямого или косвенного доступа через функции неконстантных аргументов, включая это.

означает, что вы можете безопасно называть cbegin и cend на std::vector<T>. Вызов operator== или operator< на std::string.

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

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

Несмотря на 3/, хотя, кажется, есть место для глобальных объектов, хотя, поскольку итераторы изменяют какой-то общий объект регистров, в котором они будут ассоциироваться с контейнером (функции отладки STL). Я не понимаю:

7/Реализации могут делиться своими собственными внутренними объектами между потоками, если объекты не видны пользователям и защищены от гонок данных.

в противном случае.

В любом случае стандарт гарантирует, что итерация по vector будет безопасной... но не дает никаких гарантий, когда дело доходит до фактического чтения объектов (это ваши собственные). В этом случае это покрывается, потому что std::string рассматривается выше.

EDIT: Как справедливо заметил Дэвид Хаммен, этот стандарт еще не полностью реализован. Многие компиляторы уже предоставили гарантии выше, хотя предыдущий стандарт никогда не говорил о потоках. MSVC, gcc, clang, icc, goau и т.д. Все большие имена должны уже предоставлять эту гарантию, как видно из ответа Als.

Ответ 3

В дополнение к общим правилам о предотвращении гонки данных в [container.requirements.dataraces] стандарт сообщает

-1- Для предотвращения расследований данных (17.6.5.9) реализации должны учитывать следующие функции: const: begin, end, rbegin, rend, front, back, data, find, lower_bound, upper_bound, equal_range, at и, за исключением ассоциативных или неупорядоченных ассоциативных контейнеров, operator[].

Таким образом, даже если вы вызываете неконстантный begin()/end() и т.д., если вы на самом деле ничего не модифицируете.