线程的取消学习笔记

目录

取消线程-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退出线程
相关推荐
梅雅达编程笔记8 分钟前
编程启蒙|Scratch 转 Python 系列第9天:字典/哈希表积木双向对照(AI大模型参数配置表实战)
开发语言·人工智能·python·numpy·pandas
持力行8 分钟前
C++与Java变量声明、定义及内存分配的核心区别
java·开发语言·c++
brave_zhao1 小时前
openEuler下安装tar包解压工具
linux·服务器·数据库
Rainy Blue8831 小时前
C转C++速成
c语言·c++·算法
小宏运维有点菜1 小时前
JumpServer
linux·运维
天选之子1231 小时前
DuckDB学习
jvm·学习
jinyishu_1 小时前
C++ 继承全解:从基础到高级特性
开发语言·c++
一只小菜鸡..2 小时前
Stanford CS144 学习笔记 (四):网络拥塞控制与 AIMD 算法
网络·笔记·学习
是个西兰花2 小时前
Linux:死锁与生产者消费者模型解析
linux·运维·服务器·c++·死锁·生产者消费者模型
RisunJan2 小时前
Linux命令-rsync(远程/本地文件同步 —— 增量传输的备份与镜像神器)
linux·运维·服务器