我的对象创建一个线程,该线程在其生命周期中修改了对象创建者。问题是,该线程在销毁时不应该调用对象方法。我找到了解决这个问题的方法,我想知道它是否是最好的。
class A
{
shared_ptr<int> guard = make_shared<int>(0);
public:
weak_ptr<int> getGuard() { return guard; }
void method() {}
A()
{
thread([this]
{
const auto &guard = getGuard();
while(!guard.expired())
method();
});
}
};
答案 0 :(得分:3)
您拥有的while循环不是一种线程安全的方法,只有在method
指向的对象仍然存在时才会确保guard
被调用。原因是另一个线程可能会在调用expired
和调用method
之间导致对象被破坏。
执行此检查的安全方法是尝试将弱指针提升为共享指针:
while (true)
{
shared_ptr<int> sp = getGuard().lock();
if (sp)
{
method();
}
else
{
return;
}
}
通过提升指向共享指针的弱指针,调用代码在调用method
期间参与对象的所有权,确保在调用代码使用它时不能销毁它。 / p>
您也未能加入或分离该帖子。从您的示例中看起来您想要将其分离,以便A
的构造函数可以在线程完成执行之前退出。在这种情况下,您的代码应如下所示:
thread([this]
{
...
}).detach();
答案 1 :(得分:1)
如果您想确保在调用method
时未破坏对象,但在其他时间可以销毁,则您需要保留weak_ptr
在对象本身上,并在调用方法时锁定它。类似的东西:
class A : std::enable_shared_from_this<A>
{
public:
void method() {}
A()
{
std::weak_ptr<A> self(shared_from_this());
thread([=self]
{
while (auto This = self.lock())
This->method();
}).detach();
}
};
此对象现在只能通过make_shared
创建 - 尝试以任何其他方式执行此操作会导致未定义的行为并且可能会崩溃。