成员变量在另一个线程中不会被更改?

Lie*_*mai 2 c++ multithreading c++11

几分钟前我问了一个问题,现在我遇到了一个新问题.我有这样的代码:

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();
}
Run Code Online (Sandbox Code Playgroud)

当我正在调用时theFoo.exitLoop(),running应该设置为false并且循环/线程应该退出.但是当我打电话时exitLoop(),while循环才会继续.当我检查running循环内部的值时,我得到了true,但它应该是false,所以循环退出.

当我没有使用成员变量而是使用全局变量时,一切正常.我究竟做错了什么?

Mik*_*our 12

你绑定了一个theFoo线程的副本; 所以调用exitLoop本地副本对线程使用的副本没有任何作用.相反,你可以绑定一个指针:

thread fooLoop(&foo::loop, &theFoo);
Run Code Online (Sandbox Code Playgroud)

或(包装)参考:

thread fooLoop(&foo::loop, std::ref(theFoo));
Run Code Online (Sandbox Code Playgroud)

或使用lambda并通过引用捕获:

thread fooLoop([&]{theFoo.loop();});
Run Code Online (Sandbox Code Playgroud)

你也可以通过使类不可复制来防止这样的错误:

class foo {
    foo(foo const &) = delete;             // delete the copy constructor
    void operator=(foo const &) = delete;  // delete the copy-assignment operator

    // ...
};
Run Code Online (Sandbox Code Playgroud)

您还有一个竞争条件:如果exitLoop在线程启动之前调用,则线程将running重新启动true并永远运行.您应该在构造函数中设置标志.该标志还应该是原子的,或者由互斥锁保护,以同步更新.