Является ли std::random_shuffle потокобезопасным?

В C++11 является ли алгоритм std::random_shuffle потокобезопасным (когда вызывается двумя разными потоками в двух разных контейнерах)?

И особенно эта форма:

template <class RandomIt> void random_shuffle(RandomIt first, RandomIt last);

person Vincent    schedule 18.07.2013    source источник
comment
Скорее всего, нет: эта перегрузка std::random_shuffle, вероятно, вызывает std::rand(), которая, вероятно, использует какой-то глобальный ресурс.   -  person juanchopanza    schedule 18.07.2013


Ответы (2)


Функция является потокобезопасной, если два одновременных выполнения этой функции не «работают» с одними и теми же данными. «работа» здесь означает, что ни одна из функций не может изменять данные неатомарным, непоследовательным образом. Функция может получить доступ к данным тремя способами:

  1. через параметры функции, включая объекты, на которые ссылаются эти параметры
  2. через объекты, для которых вызывается функция-член
  3. Статические функции, статические классы и глобальные данные, включая данные, используемые функциями, которые вызываются косвенно.

Поскольку random_shuffle — бесплатная функция, 2. не применяется. Однако у функции есть параметры, и она работает с ними в том смысле, что изменяет содержимое базовой последовательности. Но проблем не будет, если одновременные вызовы не будут работать с перекрывающимися последовательностями.

Остаются статические/глобальные данные. Большинство генераторов случайных чисел будут использовать какие-то глобальные данные для своего начального числа. Случайная функция по умолчанию rand не обязана быть потокобезопасной и, вероятно, не будет явно синхронизировать доступ к своему глобальному начальному состоянию.

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

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

person Arne Mertz    schedule 18.07.2013
comment
rqnd не требуется быть потокобезопасным. Это не то же самое, что сказать, что это не потокобезопасно. Любая конкретная реализация может сделать ее потокобезопасной, и ее документация должна сообщать вам об этом. - person Pete Becker; 18.07.2013
comment
@PeteBecker не обязательно означает не потокобезопасность в стандартном C++. Если конкретная реализация обеспечивает больше гарантий, чем требует стандарт, это расширение стандарта. Ответ на общий языковой вопрос, а не на конкретную реализацию. Добавление вещей может быть лучше для вашего конкретного компилятора не нужно, потому что это применимо почти ко всем уголкам языка, поскольку стандарт явно разрешает расширения. Но немного изменю формулировку про rand :-) - person Arne Mertz; 19.07.2013

Он поточно-ориентированный, если он использует поточно-ориентированный генератор случайных чисел. Генератор определяется реализацией (и, если он использует std::rand, он определяется реализацией, является ли это безопасным), поэтому вам необходимо ознакомиться с документацией по используемой вами реализации.

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

person Mike Seymour    schedule 18.07.2013