线程的取消学习笔记

目录

取消线程-pthread_cancel:

线程清理:


取消线程-pthread_cancel:

cpp 复制代码
int pthread_cancel(pthread_t thread);//杀死一个线程

示例代码:

cpp 复制代码
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *func(void *arg)
{
    printf("This is child thread\n");
    while (1)
    {
        sleep(5); //取消点
    }
    pthread_exit("thread return");
}
int main()
{
    void *retv;
    pthread_t tid;
    int i;   
    pthread_create(&tid,NULL,func,NULL);
    sleep(5);
    pthread_cancel(tid);
    pthread_join(tid,&retv);
    printf("thread ret=%s\n",(char *)retv);
    while (1)
    {
        sleep(1);
    }
}

线程取消,必须要设置取消点,如果没有则手动设置。不是说取消就取消,线程的取消点主要是阻塞的系统调用。

运行结果:

出现段错误的问题:

出错原因,retv接收不到字符串,所以不能打印。将printf那一行注释掉就可以。

手动设置取消点代码示例如下:

cpp 复制代码
void *func(void *arg)
{
    printf("This is child thread\n");
    while (1)
    {
        //sleep(5);
        pthread_testcancel();
    }
    pthread_exit("thread return");
}

设置取消使能或禁止

cpp 复制代码
int pthread_setcancelstate(int state, int *oldstate);

示例代码:

cpp 复制代码
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *func(void *arg)
{
    printf("This is child thread\n");
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);//前5秒不能取消
    //while (1)
    {
        sleep(5);
        pthread_testcancel();
    }
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);//后5秒可以取消
    while (1)
    {
        sleep(1);
    }
    pthread_exit("thread return");
}
int main()
{
    void *retv;
    pthread_t tid;
    int i;   
    pthread_create(&tid,NULL,func,NULL);
    sleep(5);//不能呢个没有sleep,因为可能线程还没禁止取消就已经取消了
    pthread_cancel(tid);
    pthread_join(tid,&retv);
    //printf("thread ret=%s\n",(char *)retv);
    while (1)
    {
        sleep(1);
    }
}

设置取消类型

cpp 复制代码
int pthread_setcanceltype(int type,int *oldtype);

PTHREAD_CANCEL_DEFERRED //等到取消点才取消(默认是这个)

PTHREAD_CANCEL_ASYNCHRONOUS //目标线程会立即取消

线程清理:

必要性: 当线程非正常终止,需要清理一些资源

cpp 复制代码
void pthread_cleanup_push(void (*routine)(void *),void *arg)
void pthread_cleanup_pop(int execute)

routine函数被执行的条件:

  1. 被pthread_cancel取消掉
  2. 执行pthread_exit
  3. 非0参数执行pthread_cleanup_pop()

示例代码:

cpp 复制代码
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void cleanup1(void *arg)
{
    printf("cleanup1, arg=%s\n",(char *)arg);
}
void cleanup2(void *arg)
{
    printf("cleanup2, arg=%s\n",(char *)arg);
}
void *func(void *arg)
{
    printf("This is child thread\n");
    pthread_cleanup_push(cleanup1, "abcd");
    pthread_cleanup_push(cleanup2, "efgh");
    //while (1)
    {
        sleep(1);
    }
    // pthread_exit("thread return");
    // pthread_cleanup_pop(0);//必须和前面成对出现
    // pthread_cleanup_pop(0);

    //等效于这种写法
    pthread_cleanup_pop(1);//必须和前面成对出现
    pthread_cleanup_pop(1);
    pthread_exit("thread return");
}
int main()
{ 
    void *retv;
    pthread_t tid;
    int i;   
    pthread_create(&tid,NULL,func,NULL);
    sleep(1);//不能呢个没有sleep,因为可能线程还没禁止取消就已经取消了
    pthread_cancel(tid);
    pthread_join(tid,&retv);
    printf("thread return = %s\n",(char *)retv);
    while(1)
    {
        sleep(1);
    }
}

运行结果:

注意:

  1. 必须成对使用,即时pthread_cleanup_pop不会被执行到也必须写上,否则编译错误。
  2. pthread_cleanup_pop()被执行且参数为0,pthread_cleanup_push回调函数routine不会被执行。
  3. pthread_cleanup_push和pthread_cleanup_pop可以写多对,routine执行顺序正好相反
  4. 线程内return可以结束线程,也可以给pthread_join返回值,但不能触发pthread_cleanup_push里面的回调函数,所以我们结束线程尽量使用pthread_exit退出线程。
相关推荐
Ruiery11 小时前
Linux 6.6内核内存管理深度解析(十六):mmap — 用户态“申请内存“的真相
linux·运维·服务器
第九序言T11 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
欧米欧11 小时前
Linux系统篇(七),环境变量的底层溯源,核心获取机制与安全应用
linux·运维·服务器
Ruiery11 小时前
Linux 6.6内核内存管理深度解析(十八):KASLR 内核地址空间随机化
linux·运维·服务器·安全
qetfw12 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
龙亘川12 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
程序喵大人12 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
Raas10013 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
专注仿真14 小时前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法
逆风的蚂蚁14 小时前
linux服务器性能调整怎么落地?我把 CPU 调度、I/O 优先级和内核参数这几个旋钮都拧了一遍
linux·运维·服务器