线程退出pthread_exit只能终止当前线程,也就是哪个线程调用了pthread_exit,哪个线程就会退出;但是线程取消pthread_cancel ,不光可以终止自己,还可以终止其他线程。
==》自己终止自己,没问题!
==》主线程调用pthread_cancel来终止子线程,没问题!
==》子线程调用pthread_cancel来终止主线程,也没有问题!(只不过这种不大常见)
目录
1、认识 pthread_cancel 函数
(1) pthread_cancel 函数介绍
(2) pthread_cancel函数实际应用:子线程自我终止、子线程终止主线程
2、其他线程取消相关函数
(1) 取消点设置函数 pthread_testcancel (了解)
(2) 线程取消使能 pthread_setcancelstate(了解)
(3) 线程取消类型设置 pthread_setcanceltype(了解)
1、认识 pthread_cancel 函数
(1) pthread_cancel 函数介绍
参数是线程ID,也就是你希望终止哪个线程;成功返回0,失败返回一个错误码。pthread_cancel 使用的前提条件是 被终止的线程有取消点,即阻塞的系统调用如sleep函数。
(2) pthread_cancel函数实际应用:子线程自我终止、子线程终止主线程
==========================子线程自我终止==========================
子线程自我终止 和 主线程终止子线程的效果是一样的,这里就只演示子线程自我终止的情况,核心代码如下,此时需要留意一下返回值
测试结果如下,我们发现,子线程提前终止,居然还会有返回值,返回值是-1,其实-1在Linux中代表的就是 PTHREAD_CANCELED
站在OS的角度,结果如下
==========================子线程终止主线程==========================
一般来说,不建议这么做,因为主线程会等待回收子线程,子线程退出就有人回收;但是子线程不会去回收主线程,所以主线程退出的时候,由于没有人回收,这个时候,主线程就会出现类似于“僵尸进程”的情况
测试结果如下,我们会发现,主线程的旁边有一个 <defunct>,defunct是死者的意思,说明这个线程已经死了,类似于“僵尸进程”
2、其他线程取消相关函数
(1) 取消点设置函数 pthread_testcancel (了解)
上面提到,被终止的线程必须要有取消点,如果没有取消点,这里可以自己手动设置一个取消点,这样的话无需 sleep 函数就可以实现线程取消了。函数声明如下:
void* thread_run(void* args)
{
pthread_testcancel(); // 设置取消点
}
int main(){
pthread_t tid;
pthread_create(&tid, NULL, thread_run, NULL);
pthread_cancel(tid); // 取消子线程
}
(2) 线程取消使能 pthread_setcancelstate(了解)
默认情况下,线程是可以被取消的,但是你如果不希望线程被取消,可以使用 pthread_setcancelstate 函数来禁止线程被取消,哪个线程要设置取消使能,那就放在哪个线程里。函数声明如下:
第一个参数state:设置线程是否取消。可选值如下:
- PTHREAD_CANCEL_ENABLE:允许当前线程取消
- PTHREAD_CANCEL_DISABLE:禁止当前线程被取消
第二个参数 oldstate:这是一个输出型参数,输出上一次线程的使能状态
void* thread_run(void* args)
{
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE); // 此时该线程不可被取消(在取消点之前)
pthread_testcancel(); // 设置取消点
// ...
}
int main(){
pthread_t tid;
pthread_create(&tid, NULL, thread_run, NULL);
pthread_cancel(tid); // 取消子线程
}
(3) 线程取消类型设置 pthread_setcanceltype(了解)
线程取消类型有两种,一种是遇到取消点再取消线程;另一种是目标线程会立马取消。默认是遇到取消点再取消。函数声明如下:
第一个参数 type:设置线程取消的类型。可选值如下:
- PTHREAD_CANCEL_DEFERRED等到取消点才取消
- PTHREAD_CANCEL_ASYNCHRONOUS目标线程会立即取消
第二个参数 oldtype:输出型参数。返回上一次的取消类型。