2

我需要使用 shared_ptr 和 weak_ptr 智能指针来解决一个场景。

两个线程,线程 1 和 2,正在使用一个名为 A 的共享对象。每个线程都有一个对该对象的引用。线程 1 决定删除对象 A,但同时线程 2 可能正在使用它。如果我使用 shared_ptr 在每个线程中保存对象 A 的引用,则该对象不会在正确的时间被删除。

我应该怎么做才能删除该对象,并防止同时使用该对象的其他线程出错?

4

2 回答 2

1

有2种情况:

一个线程拥有共享数据

如果 thread1 是对象的“所有者”,而 thread2 只需要使用它,则在 thread2 中存储一个 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 的引用者(事实上 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 回答