C++11 では、アルゴリズムstd::random_shuffleはスレッド セーフですか (2 つの異なるコンテナー上の 2 つの異なるスレッドによって呼び出された場合)?
特にこのフォーム:
template <class RandomIt> void random_shuffle(RandomIt first, RandomIt last);
C++11 では、アルゴリズムstd::random_shuffleはスレッド セーフですか (2 つの異なるコンテナー上の 2 つの異なるスレッドによって呼び出された場合)?
特にこのフォーム:
template <class RandomIt> void random_shuffle(RandomIt first, RandomIt last);
関数の 2 つの同時実行が同じデータに対して「動作」しない場合、その関数はスレッドセーフです。ここでの「作業」とは、どの関数も非アトミックで一貫性のない方法でデータを変更できないことを意味します。関数がデータにアクセスする方法は 3 つあります。
random_shuffle
無料の機能ですので、2.
適用されません。ただし、この関数にはパラメーターがあり、基になるシーケンスのコンテンツを変更するという意味で、パラメーターに対して機能します。ただし、同時呼び出しが重複するシーケンスで動作しない場合は問題ありません。
これにより、静的/グローバル データが残ります。ほとんどの乱数ジェネレーターは、シードにある種のグローバル データを使用します。デフォルトのランダム関数rand
は、スレッドセーフである必要はなく、おそらくそのグローバル シードへのアクセスを明示的に同期しません。
したがって、あなたの場合はいいえ、スレッドセーフではありません(乱数ジェネレーターがそうでない限り)。
乱数ジェネレーターの同期バージョンを作成するか、同時呼び出しで異なるジェネレーターを使用する必要があります。後者を使用することをお勧めします。そのため、同時シャッフルが相互の乱数シーケンスに干渉しません。(しかし、私は決して乱数生成の専門家ではありません)。
スレッドセーフな乱数ジェネレーターを使用する場合、スレッドセーフです。ジェネレーターは実装定義です (そして、それが を使用する場合std::rand
、それが安全かどうかは実装定義です)、使用している実装のドキュメントを参照する必要があります。
確かに、他のバリアントのいずれかを使用して、スレッドセーフなジェネレーターを提供するか、スレッドごとに個別のジェネレーターを提供する必要があります。