在C++中正确终止线程的方法是什么?

5

我正在学习多线程,我写了以下代码:

#include <iostream>
#include <mutex>
#include <thread>
#include <string>
#include <chrono>
#include <condition_variable>

int distance = 20;
int distanceCovered = 0;
std::condition_variable cv;
std::mutex mu;

void keep_moving(){
  while(true){
  std::cout << "Distance is: " << distanceCovered << std::endl;
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  distanceCovered++;
  if(distanceCovered == distance){
    cv.notify_one();
    std::terminate();
   }
 }
}

void wake_me_up()
{
  std::unique_lock<std::mutex> ul(mu);
  cv.wait( ul, []{ return distanceCovered==distance; });   // protects the lines of code below
  std::cout << "I'm here" << std::endl;
  std::terminate();
}

int main() {
  std::thread driver(keep_moving);
  std::thread wake_me(wake_me_up);
  driver.join();
  wake_me.join();

  system("pause");

  return 0;
}

从代码中可以看到,'keep_moving'线程在20秒内从0-20计数,然后通知'wake_me_up'线程打印"I'm here"并终止。通知完线程后,'keep_moving'线程也终止。

请告诉我是否以正确的方式终止了线程。运行代码后,会得到以下消息:

terminate called without an active exception
I'm here
terminate called recursively
Aborted

谢谢你。

1
为什么你认为你应该调用 std::terminate?因为你 真的 不应该这样做。 - Rob K
Rob K,我的程序从1到20进行计数,然后我想让第二个线程打印“我在这里”,然后结束。但是,之后线程1会将该值从20递增到无穷大。我认为,在主函数完成后,两个线程都会“超出范围”,所以说 :)。但显然我没有正确理解它。有没有任何方法可以实现我想要的而不做一些不推荐的事情? - Kennedy
1个回答

21

不可以。在标准C ++中,正确(也是唯一正确的)终止线程的方法是从其线程函数中返回。

std::terminate会终止整个进程。即使它只终止当前线程(例如像Win32的TerminateThread函数一样,您永远不应该调用它!),它也不会展开堆栈,也不会调用析构函数,因此可能会留下一些必要的清理未完成(例如释放互斥锁)。

std::terminate用于临界故障,即程序绝对无法继续运行的情况。 “没有活动异常”这条消息是因为terminate的主要用途是在异常系统失败时终止程序,例如由于嵌套异常,因此该函数默认查找活动异常并打印有关其信息的内容。


1
@AndyG 不行。[terminate.handler]说:“必须的行为:一个terminate_handler应该在不返回给调用者的情况下终止程序的执行。”如果你的terminate handler没有杀死你的程序,那么你的程序就有未定义的行为。 - Sebastian Redl
2
@PasserBy 是的,你可以做一些事情。然后你必须以某种方式停止进程的执行。你可以调用 std::abortExitProcess,甚至是 exec,但进程不能继续运行。如果你在一个没有进程的系统上,你可以决定进入一个无限的“闪烁警告 LED”循环。 - Sebastian Redl
2
只需写 return; - Sebastian Redl
永远不要终止线程确实是极端的做法。它有其用途。只有在您知道自己在做什么以及在牺牲什么时才调用它。它之所以存在是有原因的。 - Gaspa79
@Gaspa79 我很想听听你的使用情况。 - Sebastian Redl
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接