2

shared_ptr および weak_ptr スマート ポインターで解決する必要があるシナリオがあります。

スレッド 1 とスレッド 2 の 2 つのスレッドは、A という共有オブジェクトを使用しています。各スレッドは、そのオブジェクトへの参照を持っています。スレッド 1 はオブジェクト A を削除することを決定しますが、同時にスレッド 2 がそれを使用している可能性があります。各スレッドでオブジェクト A の参照を保持するために shared_ptr を使用した場合、オブジェクトは適切なタイミングで削除されません。

オブジェクトを削除する必要があるときにオブジェクトを削除し、そのオブジェクトを同時に使用している他のスレッドでエラーが発生しないようにするにはどうすればよいですか?

4

2 に答える 2

1

2 つのケースがあります。

1 つのスレッドが共有データを所有する

スレッド 1 がオブジェクトの「所有者」であり、スレッド 2 がそれを使用する必要がある場合は、スレッド 2 に weak_ptr を格納します。弱いポインターは参照カウントに参加しません。代わりに、オブジェクトがまだ存在する場合にオブジェクトへの shared_ptr にアクセスする方法を提供します。オブジェクトが存在しない場合、weak_ptr は空/null の shared_ptr を返します。

次に例を示します。

  class CThread2
  {
  private:
      boost::weak_ptr<T> weakPtr
  public:
   void SetPointer(boost::shared_ptr<T> ptrToAssign)
   {
        weakPtr = ptrToAssign;
   }

   void UsePointer()
   {
        boost::shared_ptr<T> basePtr;
        basePtr = weakPtr.lock()
        if (basePtr)
        {
             // pointer was not deleted by thread a and still exists,
             // so it can be used.
        }
        else
        {
             // thread1 must have deleted the pointer
        }
   }
  };

この質問に対する私の回答 (リンク) も役に立つかもしれません。

データは両方が真に所有しています

あなたのスレッドのいずれかが削除を実行できる場合、私が上で説明したことはできません。両方のスレッドは、基になるオブジェクトに加えてポインターの状態を知る必要があるため、これは「ポインターへのポインター」が役立つ場合です。

 boost::shared_ptr< boost::shared_ptr<T> >

または(生のptrを介して)

shared_ptr<T>* sharedObject;

あるいは単に

T** sharedObject;

なぜこれが役立つのですか?

  • T へのリファラーは 1 つしかありません (実際、shared_ptr はかなり冗長です)。
  • 両方のスレッドが単一の共有ポインタのステータスを確認できます (NULL ですか? 他のスレッドによって削除されましたか?)。

落とし穴: - 両側が同時に削除しようとするとどうなるかを考えてみてください。このポインターをロックする必要があるかもしれません。

改訂された例:

 class CAThread
  {
  private:
      boost::shared_ptr<T>* sharedMemory;
  public:
   void SetPointer(boost::shared_ptr<T>* ptrToAssign)
   {
        assert(sharedMemory != NULL);
        sharedMemory = ptrToAssign;
   }

   void UsePointer()
   {
        // lock as needed
        if (sharedMemory->get() != NULL)
        {
             // pointer was not deleted by thread a and still exists,
             // so it can be used.
        }
        else
        {
             // other thread must have deleted the pointer
        }
   }

   void AssignToPointer()
   {
        // lock as needed
        sharedMemory->reset(new T);
   }

   void DeletePointer()
   {
        // lock as needed
        sharedMemory->reset();
   }
  };

基礎となるデータの並行性の問題をすべて無視していますが、それはあなたが求めていることではありません。

于 2009-09-29T13:26:41.843 に答える
0

Qt には、これを行うQPointerクラスがあります。ポインターが指しているものが削除されると、ポインターは自動的に 0 に設定されます。

(もちろん、これは Qt をプロジェクトに統合することに関心がある場合にのみ機能します。)

于 2009-09-29T15:14:53.637 に答える