1. ホーム
  2. c++

[解決済み] std::shared_ptr スレッドセーフの説明

2022-08-04 23:53:52

質問

今読んでいる本 http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html を参照してください。 を読んでいますが、いくつかのスレッドセーフの問題は、私にとってまだ明確ではありません。

  1. 標準では、参照カウントがスレッドセーフに処理され、プラットフォームに依存しないことが保証されていますよね?
  2. 同様の問題 - 標準では、1 つのスレッド (最後の参照を保持) だけが共有オブジェクトの削除を呼び出すことが保証されていますよね?
  3. shared_ptr は、その中に格納されたオブジェクトに対していかなるスレッドセーフも保証しないのですか?

EDITです。

擬似的なコードです。

// Thread I
shared_ptr<A> a (new A (1));

// Thread II
shared_ptr<A> b (a);

// Thread III
shared_ptr<A> c (a);

// Thread IV
shared_ptr<A> d (a);

d.reset (new A (10));

スレッドIVでreset()を呼び出すと、最初のスレッドで作成されたAクラスの以前のインスタンスが削除され、新しいインスタンスに置き換えられますか?また、IVのスレッドでreset()を呼び出した後、他のスレッドは、新しく作成されたオブジェクトのみを参照してください?

どのように解決するには?

他の方が指摘されているように、最初の3つの質問については、正しく理解されていますね。

しかし、あなたの編集の最後の部分は

スレッドIVでreset()を呼び出すと、最初のスレッドで作成されたAクラスの以前のインスタンスが削除され、新しいインスタンスに置き換えられますか?さらにIVスレッドでreset()を呼び出した後、他のスレッドは新しく作成されたオブジェクトだけを見ることができますか?

は正しくありません。唯一 d は新しい A(10) を指すようになり a , b そして c は引き続き元の A(1) . これは,次の短い例ではっきりと見ることができます。

#include <memory>
#include <iostream>
using namespace std;

struct A
{
  int a;
  A(int a) : a(a) {}
};

int main(int argc, char **argv)
{
  shared_ptr<A> a(new A(1));
  shared_ptr<A> b(a), c(a), d(a);

  cout << "a: " << a->a << "\tb: " << b->a
     << "\tc: " << c->a << "\td: " << d->a << endl;

  d.reset(new A(10));

  cout << "a: " << a->a << "\tb: " << b->a
     << "\tc: " << c->a << "\td: " << d->a << endl;
                                                                                                                 
  return 0;                                                                                                          
}

(明らかに、私はスレッドを気にしませんでした: それは shared_ptr::reset() の動作には関係ありません)。

このコードの出力は

a: 1 b: 1 c: 1 d: 1

a: 1 b: 1 c: 1 1 d: 10