Является ли stl vector одновременным чтением потокобезопасным? - PullRequest
21 голосов
/ 17 сентября 2011

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

Я ищу следующий вариант использования:

  1. Вектор инициализируется несколькими элементами типа std :: string. (Допустим, имя объекта - strList). strList будет инициализирован во время запуска приложения.
  2. Все потоки будут перебирать strList, чтобы увидеть, соответствует ли его значение хотя бы одному элементу strList.
  3. Ни один поток не будет пытаться изменить strList, и он будет строго использоваться как объект только для чтения.

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

Ответы [ 3 ]

37 голосов
/ 17 сентября 2011

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


На самом деле, STL - неправильный способ его обозначения.
Это C ++ Стандартная библиотека .

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

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

Ссылка:

MSDN говорит:

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

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

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

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

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

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

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

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

9 голосов
/ 17 сентября 2011

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

§ 17.6.5.9 Предотвращение гонки данных

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

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

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: Как справедливо заметил Дэвид Хаммен, этот Стандарт еще не полностью реализован.Многие компиляторы уже предоставили вышеуказанные гарантии, хотя предыдущий стандарт никогда не говорил о потоках.MSVC, gcc, clang, icc, comeau и т. Д. Все крупные имена уже должны предоставить эту гарантию, как видно из ответа Алса.

2 голосов
/ 21 июня 2012

В дополнение к общим правилам об избежании гонки данных в [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() и т. Д. КакПока вы на самом деле ничего не модифицируете, это безопасно.

...