另外,如果一个主程序创建了两个线程,其中一个线程取消了另一个线程,那么被取消的线程的返回值和资源会发生什么变化?如何从主程序中知道哪个线程被取消了?因为主程序没有取消任何线程。
我正在使用异步取消。请帮忙解答。
Q1: 是的,一个线程可以取消自己。然而,这样做会有取消操作一般带来的所有负面后果;你可能想使用 pthread_exit
,它更加可预测。
Q2: 当线程被取消时,它无法生成返回值;相反,pthread_join
会将特殊值 PTHREAD_CANCELED
放入其 retval
参数所指向的位置。不幸的是,在调用 pthread_join
之前,你必须通过其他方式知道某个特定线程已经以某种方式终止,否则调用线程将永远阻塞。没有可移植的等价于 waitpid(..., WNOHANG)
或 waitpid(-1, ...)
。(手册上说“如果您认为需要此功能,则可能需要重新考虑应用程序设计”,这让我想打某个人的脸。)
Q2a: 这取决于你所说的“线程资源”。线程控制块和堆栈将被释放。所有在线程上注册的析构函数(使用pthread_cleanup_push
或 pthread_key_create
)将被执行;一些运行时还会执行堆栈上对象的 C++ 类析构函数。应用程序员有责任确保线程拥有的所有资源都由这些机制之一覆盖。请注意,其中一些机制具有固有的竞争条件;例如,不可能打开一个文件并推送一个关闭它的清理作为原子操作,因此存在取消泄漏打开文件的窗口期。(不要认为这可以通过在打开文件之前推送清理来解决,因为 deferred 取消的常见实现是在系统调用 返回 时检查它们,即恰好定时命中操作系统将文件描述符号写入返回值寄存器和调用函数将该寄存器复制到清理期望它在的内存位置之间的微小间隙。)
Qi: 你没有问这个问题,但你应该知道,启用异步取消功能的线程正式不允许做除纯计算以外的任何事情。如果调用了 任何库函数(除了 pthread_cancel
、pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED)
或 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)
),其行为是未定义的。
问题1:是的,线程可以自我取消。
问题2:如果一个线程取消了另一个线程,则其资源将一直挂起,直到主线程使用pthread_join()函数加入该线程(如果该线程是可加入的)。如果已取消的线程没有在主线程中加入,则在程序结束/终止时,资源将被释放。
问题3:我不确定,但主程序不知道哪个线程被取消了。
线程可以取消任何其他线程(在同一进程中),包括自身
线程通常没有返回值(它们只能有返回状态),线程的资源将在取消时释放
主程序可以存储线程的处理程序并测试其是否有效
pthread_join
将在其retval
参数所指向的位置放置特殊值PTHREAD_CANCELED
。请注意,这个值并不是线程的实际返回值,而是表示该线程已被取消。 - zwolvoid *
。 - zwol