1

C++11 では、アルゴリズムstd::random_shuffleはスレッド セーフですか (2 つの異なるコンテナー上の 2 つの異なるスレッドによって呼び出された場合)?

特にこのフォーム:

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

2 に答える 2

6

関数の 2 つの同時実行が同じデータに対して「動作」しない場合、その関数はスレッドセーフです。ここでの「作業」とは、どの関数も非アトミックで一貫性のない方法でデータを変更できないことを意味します。関数がデータにアクセスする方法は 3 つあります。

  1. これらのパラメーターによって参照されるオブジェクトを含む、関数パラメーターを介して
  2. メンバー関数が呼び出されるオブジェクトを介して
  3. 間接的に呼び出される関数によって使用されるデータを含む、関数の静的データ、クラスの静的データ、およびグローバル データ。

random_shuffle無料の機能ですので、2.適用されません。ただし、この関数にはパラメーターがあり、基になるシーケンスのコンテンツを変更するという意味で、パラメーターに対して機能します。ただし、同時呼び出しが重複するシーケンスで動作しない場合は問題ありません。

これにより、静的/グローバル データが残ります。ほとんどの乱数ジェネレーターは、シードにある種のグローバル データを使用します。デフォルトのランダム関数randは、スレッドセーフである必要はなく、おそらくそのグローバル シードへのアクセスを明示的に同期しません。

したがって、あなたの場合はいいえ、スレッドセーフではありません(乱数ジェネレーターがそうでない限り)。

乱数ジェネレーターの同期バージョンを作成するか、同時呼び出しで異なるジェネレーターを使用する必要があります。後者を使用することをお勧めします。そのため、同時シャッフルが相互の乱数シーケンスに干渉しません。(しかし、私は決して乱数生成の専門家ではありません)。

于 2013-07-18T10:34:22.323 に答える
3

スレッドセーフな乱数ジェネレーターを使用する場合、スレッドセーフです。ジェネレーターは実装定義です (そして、それが を使用する場合std::rand、それが安全かどうかは実装定義です)、使用している実装のドキュメントを参照する必要があります。

確かに、他のバリアントのいずれかを使用して、スレッドセーフなジェネレーターを提供するか、スレッドごとに個別のジェネレーターを提供する必要があります。

于 2013-07-18T10:27:22.367 に答える