【问题标题】:How to manage object life time using Boost library smart pointers?如何使用 Boost 库智能指针管理对象生命周期?
【发布时间】:2010-12-02 07:49:38
【问题描述】:

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

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

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

【问题讨论】:

  • 什么时候“应该”删除对象?使用shared_ptr,它会在没有人使用时被删除。您无需手动删除该对象,您相信 shared_ptr 会为您执行此操作。

标签: c++ multithreading boost concurrency ownership-semantics


【解决方案1】:

有两种情况:

一个线程拥有共享数据

如果 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
        }
   }
  };

我对这个问题的回答 (link) 也可能有用。

数据真正归双方所有

如果您的任何一个线程都可以执行删除,那么您就不能拥有我上面描述的内容。由于除了底层对象之外,两个线程都需要知道 指针 的状态,这可能是“指向指针的指针”有用的情况。

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

或(通过原始指针)

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();
   }
  };

我忽略了底层数据的所有并发问题,但这并不是你真正要问的。

【讨论】:

  • 如果没有线程是所有者怎么办。它们只是运行特定工作单元的工作线程。线程可以访问任何共享对象,并且可以更新或删除其中的一些。我没有问题是共享对象得到更新,但是如果其中一个线程删除了其中一个对象,我不希望任何线程崩溃。在我看来,我需要在两个线程中使用 weak_ptr 来引用对象,对吗?
  • 如果两个线程都不拥有对象,为什么线程要删除对象?
【解决方案2】:

Qt 有一个 QPointer 类可以做到这一点。如果指针指向的内容被删除,指针会自动设置为 0。

(当然,这只有在您有兴趣将 Qt 集成到您的项目中时才有效。)

【讨论】:

  • 这就是 boost::weak_ptr 所做的,正如 OP 所述。
猜你喜欢
  • 2012-09-13
  • 2020-06-03
  • 1970-01-01
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-06
相关资源
最近更新 更多