在Pthread库中终止线程

47
我使用 pthread_create(&thread1, &attrs, //... , //...);,如果出现某些情况需要终止这个线程,如何终止?
5个回答

74

首先,存储线程ID。

pthread_create(&thr, ...)
稍后再调用。
pthread_cancel(thr)

但是,这不是推荐的编程实践!更好的方法是使用像信号量或消息这样的线程间通信机制来通知线程停止执行。

请注意,pthread_kill(...)并没有真正终止接收线程的执行,而是向其发送一个信号,它取决于信号和信号处理程序会发生什么。


4
顺便提一下,使用pthread_cancel的问题在于,如果你使用它,那么被取消的线程中运行的代码必须理解取消点,并确保(a)它经常命中一个取消点,以便及时取消线程,(b)在发生这种情况时不会泄漏资源。这有些棘手,而如果您使用消息,则在线程何时可以退出方面,您的代码会更加明确。 - Steve Jessop
16
抱歉,pthread_cancel 是在库代码中中断可能被阻塞在系统调用上的线程的唯一干净方式。另一种方法是安装一个中断信号处理程序,并确保所有代码都准备好处理 EINTR,但库代码不能假设它有权更改信号处理或对调用者施加 EINTR 处理。 - R.. GitHub STOP HELPING ICE

29

解决这个问题有两种方法。

  • 使用信号:线程使用sigaction()安装一个信号处理函数设置一个标志,然后定期检查该标志以确定是否必须终止线程。当线程必须终止时,使用pthread_kill()向其发出信号,并使用pthread_join()等待其终止。这种方法要求父线程和子线程之间进行预同步,以确保子线程已经安装了信号处理程序,然后才能处理终止信号;
  • 使用取消点:线程在执行取消函数时终止。当线程必须终止时,执行pthread_cancel()并使用pthread_join()等待其终止。这种方法需要详细使用pthread_cleanup_push()pthread_cleanup_pop()以避免资源泄漏。最后两个调用可能会干扰代码的词法作用域(因为它们可能是产生{}标记的宏),并且非常难以正确维护。

(请注意,如果您已经使用pthread_detach()分离了线程,则无法再使用pthread_join()加入它。)

这两种方法都可能非常棘手,但在特定情况下都可以非常有用。


6

我同意Antti的看法,更好的做法是在线程检查是否应该终止时实现一些检查点。这些检查点可以用多种方式实现,例如:使用带锁的共享变量或事件,线程检查它是否已经设置(线程可以选择等待零时间)。


1
在大多数情况下,这是绝对正确的。但是,有许多情况下这是不切实际的。例如,我的当前项目是一个最小化文本编辑器,在其中我有一个专用线程来接收用户输入。由于getch()是同步操作的,我的输入线程将无法检测到它需要终止,直到用户按下另一个键。这将是非常糟糕的设计。由于用户输入线程永远不需要分配额外的资源,因此最好使用pthread_cancel()来终止它。 - user5739133

2

看看pthread_kill()函数。


-2
pthread_exit(0) 

这将终止线程。


1
这个答案是错误的。pthread_exit()是一个函数,用于终止调用该函数的线程。这是一个适当的终止方式。pthread_exit()不能用于影响任何其他线程。请不要误导。 - Animesh Kumar

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