我需要使用 shared_ptr 和 weak_ptr 智能指针来解决一个场景。
两个线程,线程 1 和 2,正在使用一个名为 A 的共享对象。每个线程都有一个对该对象的引用。线程 1 决定删除对象 A,但同时线程 2 可能正在使用它。如果我使用 shared_ptr 在每个线程中保存对象 A 的引用,则该对象不会在正确的时间被删除。
我应该怎么做才能删除该对象,并防止同时使用该对象的其他线程出错?
我需要使用 shared_ptr 和 weak_ptr 智能指针来解决一个场景。
两个线程,线程 1 和 2,正在使用一个名为 A 的共享对象。每个线程都有一个对该对象的引用。线程 1 决定删除对象 A,但同时线程 2 可能正在使用它。如果我使用 shared_ptr 在每个线程中保存对象 A 的引用,则该对象不会在正确的时间被删除。
我应该怎么做才能删除该对象,并防止同时使用该对象的其他线程出错?
有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;
为什么这很有用?
陷阱: - 想想当双方都试图同时删除时会发生什么,你可能需要锁定这个指针
修改示例:
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();
}
};
我忽略了底层数据的所有并发问题,但这并不是你真正要问的。
Qt 有一个QPointer类可以做到这一点。如果指针指向的内容被删除,指针将自动设置为 0。
(当然,这只有在您有兴趣将 Qt 集成到您的项目中时才有效。)