ブーストshared_ptrコンテナの質問
-
02-07-2019 - |
質問
マルチスレッド アプリケーションで使用されるポインターのコンテナー (std::vector) があるとします。新しいポインターをコンテナーに追加する場合、コードはクリティカル セクション (boost::mutex) を使用して保護されます。すべて順調です。コードはこれらのポインタの 1 つを処理のためにスレッドに返すことができる必要がありますが、別の別のスレッドがこれらのポインタの 1 つを削除することを選択する可能性があり、そのポインタはまだ使用されている可能性があります。例えば。:
thread1()
{
foo* p = get_pointer();
...
p->do_something();
}
thread2()
{
foo* p = get_pointer();
...
delete p;
}
そのため、スレッド 1 がポインタを使用している間に、スレッド 2 がポインタを削除する可能性があります。汚い。
したがって、代わりに Boost 共有 PTR のコンテナを使用したいと思います。IIRC では、これらのポインターは参照カウントされるため、生のポインターではなく共有 ptr を返す限り、コンテナーから 1 つを削除しても、最後に使用されるまでスコープ外になるまで実際には解放されません。つまり
std::vector<boost::shared_ptr<foo> > my_vec;
thread1()
{
boost::shared_ptr<foo> sp = get_ptr[0];
...
sp->do_something();
}
thread2()
{
boost::shared_ptr<foo> sp = get_ptr[0];
...
my_vec.erase(my_vec.begin());
}
boost::shared_ptr<foo> get_ptr(int index)
{
lock_my_vec();
return my_vec[index];
}
上記の例では、スレッド 2 が Erase を呼び出す前にスレッド 1 がポインターを取得した場合、指すオブジェクトはまだ有効ですか?スレッド1が完了しても実際には削除されないのでしょうか? グローバル ベクターへのアクセスはクリティカル セクション経由であることに注意してください。
これがshared_ptrsの仕組みだと思いますが、確認する必要があります。
解決
boost::shared_ptr のスレッドの安全性については、チェックする必要があります。 このリンク. 。安全であることは保証されていませんが、多くのプラットフォームで動作します。私の知る限り、std::vector の変更は安全ではありません。
他のヒント
上記の例では、スレッド 2 が Erase を呼び出す前にスレッド 1 がポインターを取得した場合、指すオブジェクトはまだ有効ですか?スレッド1が完了しても実際には削除されないのでしょうか?
あなたの例では、スレッド 1 がスレッド 2 よりも前にポインターを取得した場合、スレッド 2 は (ロックのため) 関数の先頭で待機する必要があります。したがって、はい、指定されたオブジェクトは引き続き有効です。ただし、最初の要素にアクセスする前に、my_vec が空でないことを確認することもできます。
さらに、(元の生ポインターの提案のように) ベクターへのアクセスを同期すると、安全に使用できます。そうしないと、他の回答者が提供したリンクの例 4 に違反する可能性があります。