几分钟前我问了一个问题,现在我遇到了一个新问题。 我有这样的代码:
class foo{
public:
void loop(){
this->running = true;
while(this->running){
// do stuff
}
}
void exitLoop(){
this->running = false;
}
private:
bool running;
};
int main(){
foo theFoo = foo();
thread fooLoop(&foo::loop, theFoo);
// do stuff
theFoo.exitLoop();
fooLoop.join();
}
当我调用theFoo.exitLoop()
时,running
应设置为false
,并且循环/线程应退出。但是当我调用exitLoop()
时,while循环才会继续。当我在循环中检查running
的值时,我得到true
,但它应该是false
,以便循环退出。
当我没有使用成员变量而是全局变量时,一切正常。 我究竟做错了什么?
答案 0 :(得分:12)
您正在将theFoo
的副本绑定到该主题;因此,在本地副本上调用exitLoop
不会对该线程使用的副本产生任何影响。相反,你可以绑定一个指针:
thread fooLoop(&foo::loop, &theFoo);
或(包装)参考:
thread fooLoop(&foo::loop, std::ref(theFoo));
或使用lambda并通过引用捕获:
thread fooLoop([&]{theFoo.loop();});
你也可以通过使类不可复制来防止这样的错误:
class foo {
foo(foo const &) = delete; // delete the copy constructor
void operator=(foo const &) = delete; // delete the copy-assignment operator
// ...
};
你也有竞争条件:如果在线程开始之前调用exitLoop
,则线程会将running
设置回true
并永远运行。您应该在构造函数中设置标志。该标志也应该是原子的,或者由互斥锁保护,以同步更新。
答案 1 :(得分:0)
即使您修复了有关复制此对象的问题,也不能使用类似的bool进行同步。优化编译器可能会注意到this->running
在该循环中不会被修改,并且可能得出结论,不需要反复检查其值。事实上,循环代码根本没有考虑其他线程的业务,它可能只是忽略它们。你必须使用atomic_bool。