C++与类成员变量的线程访问问题

Lem*_*rop 6 c++ multithreading

在使用线程一段时间后,我遇到了一种情况,我需要一个线程永远运行,直到调用一个函数(或任何类型的事件).为此,我创建了一个bool值来控制线程执行的函数内部的while循环,但我很快注意到在线程开始运行后外部变量没有更新,导致线程在被要求时永远不会停止.

下面是一些代表问题的简单代码:

#include <cstdio>
#include <thread>
#include <chrono>

class A {
public:
    A();

    void startThread();
    void endThread();
private:
    void threadCall();
    bool active;
};

int main() {
    A threadThing;
    threadThing.startThread();
    printf("[M] Thread Created\n");
    std::this_thread::sleep_for(std::chrono::seconds(5));
    threadThing.endThread();
    printf("[M] Thread Killed\n");
    std::this_thread::sleep_for(std::chrono::seconds(5));

    return 0;
}

A::A() {
    active = false;
}

void A::startThread() {
    active = true;
    std::thread AThread(&A::threadCall, *this);
    AThread.detach();
}

void A::endThread() {
    active = false;
}

void A::threadCall() {
    printf("[T] Thread Started\n");
    while (active) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
    printf("[T] Thread Ended\n");
}
Run Code Online (Sandbox Code Playgroud)

预期的结果是主函数启动线程,线程说它开始,然后4秒后线程被杀死,线程说它结束,而实际上线程永远不会说它结束.有没有办法让线程访问'active'变量,或者我的方法是否完全不正确?(旁注,我确实尝试自己解决这个问题,但只有像本地线程存储这样的东西,它似乎只是用于存储在线程中,不能访问外部但我可能是错的)

yng*_*ccc 9

问题在于构造函数std::thread,它默认复制/移动.

std::thread AThread(&A::threadCall, *this);
Run Code Online (Sandbox Code Playgroud)

这会将对象复制到新线程中,因此检查active新对象中的变量无效.

你可以删除 *

std::thread AThread(&A::threadCall, this);
Run Code Online (Sandbox Code Playgroud)

你将对象指针传递给新线程,它将像这样的方法调用(*this).threadCall().

编辑:正如评论所说,这不是保证线程安全,你需要使用std::atomic<bool>是安全的.


Jes*_*ing 5

你需要做的是将一个A类指针作为参数传递给你的线程函数.

void A::startThread()
{
    active = true;
    std::thread AThread(threadCall, this);
    AThread.detach();
}
void A::threadCall(A *aClass)
{
    printf("[T] Thread Started\n");
    while (aClass->active)
    {
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
    printf("[T] Thread Ended\n");
}
Run Code Online (Sandbox Code Playgroud)