使用线程一段时间之后,我遇到了一个情况,我需要一个线程永远运行,直到调用一个函数(或任何类型的事件)。为此,我创建了一个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");
}
预期的结果是main函数启动线程,线程说它开始,然后4秒后线程被杀死,线程说它结束了,而实际上线程永远不会说它结束了。有没有办法让线程访问“活跃的”&#39;变量,或者我对此问题的解决方法是否完全错误? (旁注,我确实尝试自己解决这个问题,但只有像本地线程存储这样的东西,它似乎只是用于存储在线程中,不能访问外部但我可能是错的)
答案 0 :(得分:9)
问题在于std::thread
的构造函数,默认情况下会复制/移动。
std::thread AThread(&A::threadCall, *this);
将对象复制到新线程中,因此检查新对象中的active
变量无效。
您可以删除*
std::thread AThread(&A::threadCall, this);
你将对象指针传递给新线程,它将像这样的方法调用(*this).threadCall()
。
编辑:正如评论所说,这并不保证线程安全,您需要使用std::atomic<bool>
才能安全。
答案 1 :(得分: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");
}