linux 线程取消点,Linux系统编程手册:线程:线程取消

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

函数pthread_cancel向由参数thread指定的线程发送一个取消请求。

#include

int pthread_cancel(pthread_t thread);

/* 成功返回0,失败返回正的errno值 */

发出取消请求后,函数pthread_cancel立即返回,不会等待目标线程的退出。

取消状态及类型

#include

int pthread_setcancelstate(int state, int *oldstate);

int pthread_setcanceltype(int type, int *oldtype);

/* 成功返回0,失败返回正的errno值 */

函数pthread_setcancelstate会将调用线程的取消状态设置为参数state所给定的值。该参数的取值可能如下:

PTHREAD_CANCEL_DISABLE

线程不可取消。如果此类线程收到取消请求,则会将请求挂起,直至将线程的取消状态置为启用。

如果线程执行的代码片段需要不间断的一气呵成,那么临时屏蔽线程的取消状态就变的很有必要。

PTHREAD_CANCEL_ENABLE

线程可以取消。这是新建线程取消状态的默认值。

如果线程的取消性状态为启用,那么对取消请求的处理则取决于线程的取消性类型。该类型可以通过调用pthread_setcanceltype指定。参数type有如下值:

PTHREAD_CANCEL_ASYNCHRONOUS

可能会在任何时点(也许是立即取消,但不一定)取消线程。异步取消的应用场景很少。

PTHREAD_CANCEL_DEFERED

取消请求保持挂起,直至到达取消点(cancellation point)。这也是新建线程的缺省类型。

当某线程调用fork时,子进程会继承调用线程的取消性类型及状态。

当某线程调用exec时,会将新程序主线程的取消性及类型分别重置为PTHREAD_CANCEL_ENABLE和PTHREAD_CANCEL_DEFERED。

取消点

若将线程的取消性状态和类型分别设置为启用和延迟,仅当线程抵达某个取消点时,线程取消请求才会起作用。

SUSv3规定,若实现提供了如下函数,则这些函数必须是取消点。

除以上函数以外,SUSv3还规定了大量函数,系统实现可以将其定义为取消点。可移植应用程序必须正确处理这一情况:线程在调用这些函数时,有可能遭到取消。

SUSv3规定,除了上述两组必须或可能是取消点的函数之外,不得将标准中的任何其他函数视为取消点(亦即,调用这些函数不会招致线程取消,应用程序无需加以处理)。系统实现可随意将标准并未规范的其他函数标记为取消点。

线程一旦收到取消请求,且启用了取消性状态并将类型设置为延迟,则其会在下次抵达取消点时终止。如果该线程尚未分离,那么为防止其变为僵尸线程,必须由其他线程对其进行连接(join)。连接之后,返回至函数pthread_join中第二个参数的将是一个特殊值PTRHEAD_CANCELED。

线程可取消性的检测

假设程序执行的是一个不含取消点的计算密集型循环,这时,线程永远不会相应取消请求。

#include

void pthread_testcancel(void);

函数pthread_testcancel的目的很简单,就是产生一个取消点。线程如果已有处于挂起状态的取消请求,那么只要调用该函数,线程就会随之终止。

清理函数(cleanup handler)

线程可以设置一个或多个清理函数,当线程遭取消时会自动运行这些函数,在线程终止之前可执行诸如修改全局变量,解锁互斥锁等操作。

每个线程都可以拥有一个清理函数栈。当线程遭取消时,会延该栈自顶向下依次执行清理函数,首先会执行最近设置的函数,接着是次新的函数,以此类推。当执行完所有的清理函数后,线程终止。

#include

void pthread_cleanup_push(void (*routine)(void *), void *arg);

void pthread_cleanup_pop(int execute);

pthread_cleanup_push会将参数routine所指向的函数添加到调用线程的清理函数栈顶。

通常,线程若在执行一段特殊代码时遭到取消,才需要执行清理动作。如果线程顺利执行完这段code而未遭到取消,那么就不在需要清理。所以,每个对pthread_cleanup_push的调用都会伴随着pthread_cleanup_pop的调用。此函数从清理函数栈顶移除一个函数,如果参数execute非0,那么无论如何都会执行清理函数。在线程未遭取消而又希望执行清理动作时,这会非常方便。

为了便于编码,若线程因调用pthread_exit而终止,则也会执行清理函数栈中的清理函数。线程正常返回(return)时不会执行清理函数。

异步取消

如果设置线程为可异步取消时(取消性类型为PTHREAD_CANCEL_ASYNCHRONOUS),可以在任何时间点将其取消,取消动作不会拖延到下一个取消点才进行。

异步取消的问题在于,尽管清理函数依然会得以执行,但清理函数却无从得知线程的具体状态(延迟取消只会在取消点取消,线程状态已知)。换句话说,清理函数不清楚需要执行哪些清理步骤,另外,线程也有可能在malloc的调用期间被取消,这极有可能造成后续的混乱。

作为一般性原则,可异步取消的线程不应该分配任何资源,也不能获取互斥量或锁。这导致大量库函数无法使用。换言之,异步取消功能鲜有应用场景,其中之一就是:取消在执行计算密集型循环的线程。

总结

函数pthread_cancel允许某线程向另一个线程发送取消请求,请求目标线程取消(终止)。

目标线程如何响应,取决于其取消性状态和类型。如果禁用线程的取消性状态,那么请求会保持挂起(pending)状态,直至将线程的取消性状态置为启用。如果启用取消性状态,那么线程何时响应取消请求取决于取消性类型。若类型为延迟取消,则在线程到达取消点时,取消发生。如果为异步取消类型,取消动作随时可能发生(鲜有使用)。

线程可以设置一个清理函数栈,当线程遭到取消(或调用pthread_exit)时,会自动调用这些函数以执行清理工作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值