[英]Is starting an std::thread in a class constructor thread safe?
所以我有一个类似这样的代码(C++11):
class Foo
{
private:
std::vector<int> vec;
int val;
std::thread Foo_thread;
public:
Foo();
void StartLoop();
void WaitTermination() { this->Foo_thread.join(); }
void AddToVec(int dummy) { vec.push_back(dummy); }
void setter(int val) { this->val = val; }
};
void Foo::StartLoop()
{
while (true)
{
// some code . . .
this->vec.push_back(something);
}
}
Foo::Foo()
{
this->Foo_thread = std::thread(&Foo:SartLoop, this);
}
int main()
{
Foo* f = new Foo{};
f->WaitTermination();
}
如果我理解得很好,f 指针和 Foo 实例存在于主线程中。 在构造函数中, this->Foo_thread = std::thread(&Foo:SartLoop, this);
,Foo 实例的地址被传递给 std::thread,因此该线程可以访问该对象的成员,例如在 Foo::StartLoop(): this->vec.push_back 中。
然而,Foo 类有一个公共的 AddToVec(),所以在 main() 中我可以写:
int main()
{
Foo* f = new Foo{};
f->AddToVec(78); // at this point, we modify the private vec member, both from the main thread and in the std::thread, if I undersand well
f->setter(67); // same problem, however it's easier to declare val as std::atomic<int>, but the above one is really problematic
f->WaitTermination();
}
我的问题是,我理解得好吗? 我该如何修复此代码? 我想保留构造函数创建线程机制。
谢谢
它导致数据竞争调用 f->AddToVec(78); f->setter(67); 在主要。 没有它们,使用this
指针访问正在构造的对象是安全的,因为它不是 UB 并且语言标准不禁止这样做。 但在实践中,不推荐在构造中使用this
,并且有经验的开发人员通常会尽量避免,因为随着代码的发展,它会导致问题:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.