线程取消(Thread cancellation)是在线程完成之前来终止线程。

例如:多个线程并发执行搜索数据库,且其中一个线程已经取得结果,那么其他线程可以取消。

被取消的线程通常被称为目标线程(target thread)

取消一个目标线程可能发生在两个不同的场景:

  1. 异步取消(Asynchronous cancellation):一个线程立即终止目标线程。
  2. 延迟取消(Deferred cancellation):目标线程定期检查自己是否应该终止,这允许目标线程有机会以有序方式来终止自己。

当资源被分配给一个被取消的线程,或者要取消的线程正在更新与其他线程共享的数据时,那么线程取消就会遇到麻烦。尤其对于异步取消非常麻烦。

通常,操作系统会从被取消的线程中回收系统资源,但不会回收所有资源。因此,异步取消线程可能无法释放必要的系统资源。

对于延迟取消,则相反,一个线程指示目标线程被取消,但是只有在目标线程检查了一个标志以确定是否应该取消它之后才会发生取消。线程可以在一个可以被安全取消的点上执行此检查。

在Pthreads中,线程取消使用pthread_cancel()函数。目标线程的标识符作为参数传递给该函数。

pthread t tid;
/ * 创建线程
* /
pthread_create(&tid, 0, worker, NULL);
. . .
/ * 取消线程
* /
pthread_cancel(tid);

调用pthread_cancel()只表示要取消目标线程的请求。然而,真实的取消取决于目标线程是如何设置来处理这个请求的

Pthreads支持三种取消模式,每个模式定义为一个状态和一个类型,如下表所示。一个线程可以使用一个API来设置它的取消状态和类型:

模式(Mode) 状态(State) 类型(Type)
Off Disabled -
Deferred(延迟) Enabled Deferred
Asynchronous (异步) Enabled Asynchronous

Pthreads允许线程关闭(disabled)或者开启(enabled)线程取消。

显然,如果取消(disabled)了线程取消,则不能取消线程。但是,取消请求仍在等待中,因此线程可以稍后启用(enabled)线程取消并响应请求。

默认的线程取消类型是延迟取消(deferred cancellation)。在延迟取消模式下,只有当线程到达了取消点(cancellation point),线程取消才会发生。

建立取消点的一种技术是调用pthread_testcancel()函数。如果发现取消请求正在等待,将调用一个名为清除处理程序(cleanup handler)的函数。该函数允许在线程终止之前,释放掉线程可能获得的任何资源。

下面的代码说明了线程如何使用延迟取消来响应取消请求:

while (1) {
/ * do some work for awhile
* /
/ * . . .
* /
/ * check if there is a cancellation request
* /
pthread testcancel();
}

由于前面描述的问题,在Pthreads文档中不推荐异步取消。

有趣的是,在Linux系统上,使用Pthreads API的线程取消是通过信号来处理的(第4.6.2节)。

results matching ""

    No results matching ""