pthread_cancel为何无法取消掉一个线程

pthread_cancel如何取消线程
首先了解pthread_cancel取消线程的机制

线程可以通过调用pthread_cancel函数来取消同一进程中的其他线程

pthread_cancel函数
#include <pthread.h>
int pthread_cancel(pthread_t tid);
成功取消返回0 不成功返回非0

pthread_cancel 函数的作用会像调用参数为PTHREAD_CANCELED的pthread_exit函数一样,使线程终止。

但是,pthread_cancel 并不等待线程终止它仅仅是个请求。

线程再收到pthread_cancel 的取消请求后,可能会忽略,立即取消或者运行至取消点取消。系统默认情况下,收到取消请求后,线程会继续运行到,下一个取消点处终止进程。

取消点:取消点是线程检查它是否被取消的一个点,posix保证再一些函数取消点一定会出现如 sleep accept write read等

一个死循环的线程,没有取消点(一些函数会自带取消点,所以为了死循环,不在其中添加任何函数),无法被取消。

[wens@localhost pthread_cancel]$ cat test.cpp 
#include <iostream>
#include <unistd.h>
#include <pthread.h>
using namespace std;

void* thread(void* arg)
{
  while(1)
  {
    //其中不调用一些自带取消点的函数。
  }

}

int main()
{

  pthread_t id;
  pthread_create(&id,NULL,thread,(void*)"thread");

  pthread_cancel(id);
 cout<< "bbbbbbb"<<'\n';
  pthread_join(id,NULL);
  return 0;
}

运行该函数,将会是一个持续的死循环,pthread_cancel该函数已经运行过,取消请求也已发送,但线程并不会终止。

之前已经说过,默认情况是,收到取消请求后,线程将会运行到函数内部的取消点后终止函数即系统默认的可取消状态是PTHREAD_CANCEL_ENABLE,当线程的可取消状态是PTHREAD_CANCEL_DISABLE时,线程收到取消请求在取消点也不会取消,直到可取消状态变更为PTHREAD_CANCEL_ENABLE时,线程将会在下一个取消点取消。所以说,除了线程是否取消,与取消点有关外,还会和取消状态有关。

可取消状态 分为 PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_DISABLE

可通过一个函数来修改线程的取消状态

pthread_setcancelstate(int state ,int *oldstate);
state:设置新状态
oldstate:存放原先的取消状态

在保证取消状态的前提下,我们还需要一个取消点

所以在死循环中我们需要一个取消点,在posix的标准中提供了一写函数自带取消点,如之前说过的sleep write read wait 等一系列函数。

除了这些pthread 库还提供了一个一个函数可以设置一个取消点

 int pthread_testcancel(void);
 成功返回0 失败返回一个错误码

该函数会在函数内部设置一个取消点,调用该函数时,如果收到一个取消请求,且取消状态是可取消的,就会立即将线程取消。如果取消状态为不可取消,且没有取消请求,就不会取消,直到两者条件都满足时。

我们可以在while循环中直接掉用pthread_testcancel() 或者sleep() 或者用cout输出(底层调用write),此时都可以将线程取消。

在线程的属性中还有一个属性与线程的取消有关,即它的取消类型,之前我们所说的取消属于推迟取消,在调用pthread_cancel函数后,需要线程运行至一个取消点时,线程才会取消。

而在此时还有一种取类型为异步取消,即为当调用pthread_cancel后,线程就会立即取消调,而不用等到运行到取消点时再取消线程,取消类型同取消状态一样可以修改。

pthread_setcanceltype(int type,int* oldtype);
//参数意义与设置状态的意义相同
       
可选类型:PTHREAD_CANCEL_DEFERRED :线程接收到取消操作后,直到运行到“可取消点”后取消。 
          PTHREAD_CANCEL_ASYNCHRONOUS :线程接收到取消操作后,立即取消。

在while中使用pthread_setcanceltype设置,在可取消状态下,当有取消请求时,线程就可立即取消。

“可取消性”和“可取消类型”存在于任意一个新建线程中,包括主线程,默认设置是PTHREAD_CANCEL_ENABLE 和 PTHREAD_CANCEL_DEFERRED。
在说一下个人关于取消点的理解,posix提供的一系列自带取消点的函数,经过分析可以发现大部分函数都有一些共同的特点,就是阻塞式的系统调用或花费时间较大的IO操作,而这些操作势必会陷入内核态,而我们知道系统在从内核态切回用户态时会进行一个信号的检查,如果收到信号就会处理信号,而取消信号应该就是在此时被处理,从而取消掉线程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值