7

スレッド間でデータを共有し、最後のユーザーがデータを使い終わったときに自動的に削除したいと考えています。これは、ほとんどの場合、セグメントで使用boost::interprocess::shared_ptrするとboost::fixed_managed_shared_memory機能するようですが、常にではありません。

では、boost::interprocess::shared_ptrスレッド (およびインタープロセス) は安全ですか?

固定アドレスで共有メモリを使用している場合 (これは 64 ビット (まあ、48 ビット) アドレス空間では問題ないと確信しています)、通常のboost::shared_ptr(これはスレッドセーフ) 代わりに?

明確化:

私が使用するポインター型は plainvoid*です (私の共有メモリーは固定アドレスにマップされています)。

スレッドセーフの問題は、参照カウントに関するものです。つまり、異なるプロセスで同時に同じものへの共有ポインタをコピー/破棄することが許可されているかどうかです。異なるスレッドで同じ共有ポインタにアクセスしないでください。また、ポインティにアクセスしないでください。

4

6 に答える 6

5

で使用される参照カウントは、boost::interprocess:shared_ptrで定義されたアトミック カウンターを使用して実装されboost/interprocess/detail/atomic.hpp、 refcount ロジックは主に で実装されboost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hppます。その意図は、refcount をスレッド (およびインタープロセス) セーフな方法で処理することです。

アトミック操作の実装は、特定のターゲット プラットフォームによって異なります (Windows は Win32 インターロック API を使用し、一部のプラットフォームはさまざまなインライン アセンブリを使用するなど)。ターゲットにしているプラ​​ットフォームを知っておくと役立つ場合があります。私はそれを期待していませんが、refcount 処理でバグに遭遇している可能性があると思います。

上記の回答を、具体的に対処したい領域に限定しました。

スレッドセーフの問題は、参照カウントに関するものです。つまり、異なるプロセスで同時に同じものへの共有ポインタをコピー/破棄することが許可されているかどうかです。異なるスレッドで同じ共有ポインタにアクセスしないでください。また、ポインティにアクセスしないでください。

そうは言っても、おそらく上記のアイテムによって、または何らかの方法で「独立した」boost::interprocess:shared_ptrオブジェクトを作成することによって導入されたバグを調べます(異なるshared_ptrs が異なる参照カウントを使用して同じオブジェクトを参照する場合)。この状況は、未加工のオブジェクト ポインターを引き続き使用したり渡したりするコードがある場合に、簡単に発生する可能性があります。

于 2011-04-28T05:58:41.833 に答える
1

boost::shared_ptr<T>プロセス間セーフではないため、このコンテキストでマルチスレッドセーフであるかどうかは議論の余地があります。(このステートメントは、プログラムの操作が行われBOOST_SP_DISABLE_THREADSていないことを前提としています。)#defined

boost::interprocess::shared_ptr<T>は、その性質上、クロスプロセスセーフであり、マルチスレッドセーフであるように設計されています。最後の参照が範囲外になると、ポイントされたオブジェクトをクリーンアップできます。明らかに、このクリーンアップは、オブジェクトに使用される共有メモリ セグメントの範囲内で行われます。

は多くのプラットフォームでバージョン 1.33.0 のロックフリー カウント メカニズムをboost::shared_ptr<T>使用するため、セグメント内のオブジェクトのクロスプロセス削除が成功する可能性はごくわずかであるため、可能性はほとんどありません。メンテナをブーストします。shared_memory

于 2011-04-24T19:44:38.480 に答える
0

「これは、ほとんどの場合、boost ::interprocess::shared_ptrをboost::fixed_managed_shared_memoryセグメントで使用すると機能するようですが、常に機能するとは限りません。」必ずしも削除が機能しないことを意味するわけではない場合:スレッドセーフコンテナでセマフォを使用するだけです。このセマフォはスレッドセーフを改善するものではありませんが、データを使用するユーザーの数を確認し、制限することもできます。セマフォが0の場合、ユーザーはもういません。共有データを安全に削除してください。そこにユーザーが1人だけの場合、これは1になるので、ユーザーが要求したデータをコピーし、共有コンテナーを削除してから、コピーを返します。

于 2011-04-25T08:27:27.523 に答える
0

ええと。スレッドセーフではないことboost::shared_ptrは間違いありません。少なくとも eg よりもスレッドセーフではありません。複数のスレッドからa を読み取ることができますが、いずれかのスレッドが a を書き込んでいるとすぐに、他のライターおよびリーダーと同期する必要があります。std::vectorboost::shared_ptrboost::shared_ptr

いいえ、共有メモリで使用することはできません。そのように設計されたことはありません。たとえば、参照カウントとデリータを格納するいわゆる「共有カウント」オブジェクトを使用し、その共有カウント オブジェクトはshared_ptrコードによって割り当てられるため、共有メモリには常駐しません。また、shared_ptrコード (および vtables のようなメタデータ) は、異なるプロセスではまったく異なるアドレスにある可能性があるため、仮想関数呼び出しも問題になります (IIRCshared_ptrは仮想関数を内部で使用するか、少なくとも関数ポインターを使用し、同じ問題につながります)。 )。


プロセス間セーフかどうかはわかりませんが、そうではないことは確かです。boost::interprocess::shared_ptrプロセス間同期はかなり高価です。boost::interprocess::shared_ptr そうしないと、ユーザーが共有データへのアクセスをブロックする可能性があります。そうすれば、高い同期コストは、連続して複数のアクセスに対して 1 回支払うだけで済みます。

編集: Eamon Nerbonne が彼のコメントで参照した使用パターン (これは でスレッドセーフです) も で OK であると期待しています。一概には言えませんが。boost::shared_ptrboost::interprocess::shared_ptr

于 2011-03-27T03:51:19.920 に答える
0

shared_ptr.hpp のコードとブースト Web サイトのドキュメントを見ると、使用する内部ポインターの型を決定する 2 番目のテンプレート パラメーターに応じて、単一のインスタンスの逆参照がスレッドセーフである場合とそうでない場合があるように見えます。具体的には、「内部ポインターは typename VoidAllocator::pointer 型と同じポインター型になります (つまり、typename VoidAllocator::pointer が offset_ptr の場合、内部ポインターは offset_ptr になります)。」逆参照はこのクラスの get()/get_pointer() メソッドの結果を返すだけなので、おそらくそれに完全に依存するはずです。Boost::shared_ptr は、同時読み取り専用アクセスが必要な場合に機能します。複数のスレッドからの書き込みアクセスの場合、offset_ptr をモデルにした独自のラッパーを作成する必要がある場合があります。

于 2011-04-25T14:17:34.613 に答える
0

pgroke が暗示しているように (反対票の理由がわからない)、核となる問題は、異なるスレッドまたはプロセスから同じshared_ptr インスタンスにアクセスしているかどうかです。

shared_ptr (プロセス間かどうか) はこのシナリオをサポートしていないため、安全ではありません。

一方、shared_ptr は、複数の (スレッド プライベート、または他のメカニズムによる同時変更から保護された) 共有ポインター インスタンスが同じオブジェクトを指すように設計されており、同じオブジェクトへのこれらのポインターの異なるインスタンスを同時に変更する必要はありません。問題。

::interprocess:: ここでは主にレッドニシンです - ポインタのスレッドセーフを変更せず、プロセスプライベートメモリなどを参照する内部ポインタがないことを確認するだけです.

では、どちらのケースでしょうか。

于 2011-04-26T00:12:42.250 に答える