web-dev-qa-db-ja.com

std :: vectorまたはboost :: vectorスレッドセーフですか?

_std::vector_の共有オブジェクトでPush_back()を同時に呼び出す複数のスレッドがあります。 _std::vector_スレッドは安全ですか?または、スレッドセーフにするために自分でメカニズムを実装する必要がありますか?
余分な"locking and freeing"作業を避けたいのは、私がライブラリデザイナーではなくライブラリユーザーだからです。ベクトル用の既存のスレッドセーフなソリューションを探したいと思っています。 boost 1.48.以降から新しく導入された_boost::vector_についてはどうでしょう。スレッドセーフですか?

35
Jacky Lee

C++標準は、標準C++ライブラリのすべてのクラスに対して特定のスレッド化保証を行います。これらの保証はあなたが期待するものではないかもしれませんが、すべての標準C++ライブラリクラスに対して特定のスレッドの安全性が保証されています。ただし、標準のC++コンテナのスレッド化の保証は通常、期待するものと一致しないため、行われた保証を必ずお読みください。異なるクラス、通常はより強力なクラスについては、保証が行われ、以下の回答は特にコンテナに適用されます。コンテナには、基本的に次のスレッド安全性の保証があります。

  1. 同じコンテナの複数の同時リーダーが存在する可能性があります
  2. 作家が1人いる場合、作家と読者はもういません。

これらは通常、人々がスレッド安全性の保証として望むものではありませんが、標準コンテナのインターフェースを考えると非常に合理的です。複数のアクセススレッドがない場合に効率的に使用されることを意図しています。メソッドに何らかのロックを追加すると、これが妨げられます。これを超えて、コンテナのインターフェースは、内部ロックのどの形式にも実際には役立ちません。通常、複数のメソッドが使用され、アクセスは以前のアクセスの結果に依存します。たとえば、コンテナがempty()ではないことを確認した後、要素にアクセスできます。ただし、内部ロックでは、実際にアクセスされたときにオブジェクトがまだコンテナ内にあるという保証はありません。

上記の保証を提供する要件を満たすには、おそらく同時にアクセスされるコンテナに対して何らかの形式の外部ロックを使用する必要があります。ブーストコンテナーについては知りませんが、標準コンテナーのインターフェイスと同様のインターフェイスがある場合、まったく同じ保証があると思われます。

保証と要件は、17.6.4.10 [res.on.objects]パラグラフ1に記載されています。

異なるスレッドから標準ライブラリ関数を呼び出すとデータ競合が発生する可能性がある場合、プログラムの動作は未定義です。これが発生する可能性のある条件は、17.6.5.9で指定されています。 [注:スレッド間で共有される標準ライブラリタイプのオブジェクトを変更すると、そのタイプのオブジェクトがデータ競合なしで共有可能として明示的に指定されない限り、またはユーザーがロックメカニズムを提供しない限り、未定義の動作のリスクがあります。 —巻末注]

...および17.6.5.9 [res.on.data.races]。このセクションでは、基本的に、非公式のより非公式な説明について詳しく説明します。

54
Dietmar Kühl

Std :: vectorの共有オブジェクトでPush_back()を同時に呼び出す複数のスレッドがあります。 std :: vectorスレッドセーフですか?

これはnsafeです。

または、スレッドセーフにするために自分でメカニズムを実装する必要がありますか?

はい。

私はライブラリデザイナーではなくライブラリユーザーなので、余分な「ロックと解放」作業を避けたいと思います。ベクトル用の既存のスレッドセーフなソリューションを探したいと思っています。

さて、ベクターのインターフェースは同時使用には最適ではありません。クライアントがロックにアクセスできる場合は問題ありませんが、インターフェイスが各操作のロックを抽象化するために-いいえ。実際、Vectorのインターフェースは、外部ロックなしでスレッドの安全性を保証することはできません(変更する操作が必要であると仮定)。

Boost 1.4:以降から新たに導入されたboost :: vectorはどうですか。スレッドセーフですか?

ドキュメントの状態:

//! boost::container::vector is similar to std::vector but it's compatible
//! with shared memory and memory mapped files.
27
justin

Std :: vectorの共有オブジェクトでPush_back()を同時に呼び出す複数のスレッドがあります。 ...ベクトル用の既存のスレッドセーフソリューションを探したいと思います。

を見てみましょう concurrent_vector in IntelのTBB 。厳密に言えば、std::vectorは内部的に使用され、APIによる完全な互換性はありませんが、それでも適切な場合があります。その設計と機能の詳細を見つけることができます TBB開発者のブログで

9
Alexey Kukanov