线程的取消学习笔记

目录

取消线程-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退出线程
相关推荐
萤丰信息2 分钟前
技术赋能安全:智慧工地构建城市建设新防线
java·大数据·开发语言·人工智能·智慧城市·智慧工地
小张的博客之旅9 分钟前
宁波市第八届网络安全大赛初赛(REVERSE-Writeup)
学习·网络安全·reverse
Pocker_Spades_A24 分钟前
飞算JavaAI家庭记账系统:从收支记录到财务分析的全流程管理方案
java·开发语言
正在努力的小河1 小时前
Linux设备树简介
linux·运维·服务器
荣光波比1 小时前
Linux(十一)——LVM磁盘配额整理
linux·运维·云计算
墨雨听阁1 小时前
8.18网络编程——基于UDP的TFTP文件传输客户端
网络·网络协议·学习·udp
小晶晶京京1 小时前
day35-负载均衡
运维·网络·网络协议·学习·负载均衡
LLLLYYYRRRRRTT1 小时前
WordPress (LNMP 架构) 一键部署 Playbook
linux·架构·ansible·mariadb
CHEN5_022 小时前
【Java基础常见辨析】重载与重写,深拷贝与浅拷贝,抽象类与普通类
java·开发语言
轻松Ai享生活2 小时前
crash 进程分析流程图
linux