简体   繁体   English

如何正确结束线程?

[英]How to end a thread properly?

My main program creates a thread.我的主程序创建了一个线程。 This thread initializes some data then enters a 'while' loop and runs until the main program sets the control variable to 'false'.该线程初始化一些数据,然后进入“while”循环并运行,直到主程序将控制变量设置为“false”。 Then it calls join() witch blocks the whole code endlessly.然后它调用 join() 女巫无休止地阻塞整个代码。

bool m_ThreadMayRun;

void main(){
   thread mythread = thread(&ThreadFunction);
   //do stuff
   m_ThreadMayRun = false;
   mythread.join(); // this blocks endlessly even when I ask 'joinable' before
}

void ThreadFunction{
   initdata();
   m_ThreadMayRun=true;
   while(m_ThreadMayRun){
   //do stuff that can be / has to be done for ever
   }
   deinitdata();
}
  • Am I missing something here?我在这里错过了什么吗?
  • What would be a proper solution to make the loop leave from the main thread?使循环离开主线程的正确解决方案是什么?
  • Is it at all necessary to call join?是否有必要调用加入?

Thanks for help感谢帮助

You have a race condition for two threads writing to m_ThreadMayRun .您有两个线程写入m_ThreadMayRun的竞争条件。 Consider what happens if first the main thread executes m_ThreadMayRun = false;考虑如果首先主线程执行m_ThreadMayRun = false;会发生什么and then the thread you spwaned executes m_ThreadMayRun = true;然后你创建的线程执行m_ThreadMayRun = true; , then you have an infinite loop. ,那么你有一个无限循环。 However, strictly speaking that line of reasoning is irrelevant, because when you have a race condition your code has undefined behavior.然而,严格来说,这条推理线是无关紧要的,因为当你有竞争条件时,你的代码会有未定义的行为。

Am I missing something here?我在这里错过了什么吗?

You need to synchronize access to m_ThreadMayRun by making it either an std::atomic<bool> or using a std::mutex and make sure that m_ThreadMayRun = false is executed after m_ThreadMayRun = true;您需要通过使其成为std::atomic<bool>或使用std::mutex来同步对m_ThreadMayRun的访问,并确保在m_ThreadMayRun = false = true 之后执行m_ThreadMayRun = true; . .

PS For this situation it is better to use a std::condition_variable . PS对于这种情况,最好使用std::condition_variable

The issue is that access to bool m_ThreadMayRun;问题是访问bool m_ThreadMayRun; is not synchronized, and according to C++ rules, each thread may assume it does not change between threads.是不同步的,并且根据 C++ 规则,每个线程可以假设它在线程之间没有变化。 So you end up with a race (a form of undefined behavior).所以你最终会遇到一场比赛(一种未定义的行为)。

To make the intention clear, make it atomic .为了明确意图,使其成为atomic的。

std::atomic<bool> m_ThreadMayRun;

With this every load/store of m_ThreadMayRun becomes a memory fence, which not only synchronizes its own value, but also makes other work done by the thread visible, due to the acquire/release semantics of an atomic load/store.这样, m_ThreadMayRun的每个加载/存储都变成了 memory 栅栏,由于原子加载/存储的获取/释放语义,它不仅同步了自己的值,而且还使线程完成的其他工作可见。

Though there is still a small race possible between m_ThreadMayRun = true in the thread and setting m_ThreadMayRun = false .尽管线程中的m_ThreadMayRun = true和设置m_ThreadMayRun = false之间仍然可能存在小竞争。 Either one can execute first, sometimes leading to undesired results.任何一个都可以先执行,有时会导致不希望的结果。 To avoid this, initialize it to true before starting the thread.为避免这种情况,请在启动线程之前将其初始化为true

std::atomic<bool> m_ThreadMayRun;

void main(){
   m_ThreadMayRun = true;
   thread mythread(&ThreadFunction);
   //do stuff
   m_ThreadMayRun = false;
   mythread.join(); // this blocks endlessly even when I ask 'joinable' before
}

void ThreadFunction{
   initdata();
   while(m_ThreadMayRun){
   //do stuff that can be / has to be done for ever
   }
   deinitdata();
}

For more details about memory fences and acquire/release semantics, refer to the following excellent resources: the book " C++ Concurrency in Action " and Herb Sutter's atomic<> weapons talk.有关 memory 栅栏和获取/释放语义的更多详细信息,请参阅以下优秀资源:《 C++ Concurrency in Action 》一书和 Herb Sutter 的atomic<>武器谈话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM