什么是线程取消?
在线程完成之前终止它被称为**线程取消**。例如,如果多个线程并发地搜索数据库,而一个线程返回结果,则可以取消其余线程。另一种情况可能是用户按下网页浏览器上的按钮,阻止网页进一步加载。网页加载通常使用多个线程——每个图像都在单独的线程中加载。当用户在浏览器上按下停止按钮时,将取消加载页面所有线程。要取消的线程通常称为目标线程。目标线程的取消可能发生在两种不同的情况下:
**异步取消** - 一个线程立即终止目标线程。
**延迟取消** - 目标线程定期检查是否应终止,从而使其有机会以有序的方式自行终止。
取消的困难出现在已向已取消线程分配资源或线程在更新与其他线程共享的数据过程中被取消的情况下。这在异步取消中尤其麻烦。许多时候,操作系统将从已取消的线程中回收系统资源,但不会回收所有资源。因此,异步取消线程可能无法释放必要的系统范围资源。相反,对于延迟取消,一个线程指示要取消目标线程,但只有在目标线程检查标志以确定是否应取消后才会发生取消。线程可以在可以安全取消的点执行此检查。在 Pthreads 中,使用 pthread_cancel() 函数启动线程取消。目标线程的标识符作为参数传递给该函数。以下代码演示了创建并随后取消线程:
示例
pthread t tid; /* create the thread */ pthread create(&tid, 0, worker, NULL); … /* cancel the thread */ pthread cancel(tid);
调用 pthread_cancel() 仅表示取消目标线程的请求;实际取消取决于目标线程如何设置以处理请求。Pthreads 支持三种取消模式。每种模式都定义为状态和类型,如下表所示。它的取消状态和类型可以使用 API 由线程设置。
模式 | 状态 | 类型 |
---|---|---|
关闭 | 禁用 | - |
延迟 | 启用 | 延迟 |
异步 | 启用 | 异步 |
如表所示,Pthreads 允许线程禁用或启用取消。显然,如果禁用取消,则无法取消线程。但是,取消请求仍然挂起,因此线程可以稍后启用取消并响应请求。默认取消类型是延迟取消。在这里,只有当线程到达取消点时才会发生取消。建立取消点的一种技术是调用 pthread_testcancel() 函数。如果发现取消请求正在挂起,则会调用称为清理处理程序的函数。此函数允许释放线程可能已获取的任何资源,然后才能终止线程。以下代码演示了线程如何使用延迟取消响应取消请求:
while (1){ /* do some work for a while */ /* ... */ /* check if there is a cancellation request */ pthread testcancel(); }