线程的取消学习笔记

目录

取消线程-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退出线程
相关推荐
net3m335 分钟前
雅特力单片机用串口USART_INT_TDE中断比用USART_INT_TRAC的 发送效率要高
java·开发语言·算法
爱打代码的小林8 分钟前
python基础(逻辑回归例题)
开发语言·python·逻辑回归
一过菜只因22 分钟前
JavaWeb后端(spring--boot)
java·开发语言
五仁火烧27 分钟前
安装rust开发环境
开发语言·后端·rust
richxu2025100127 分钟前
嵌入式学习之路>单片机核心原理篇>(14) ARM 架构
arm开发·单片机·学习
WG_1731 分钟前
Linux:环境变量
linux·运维·服务器
努力的小帅32 分钟前
Linux_基础IO(Linux入门到精通)
linux·动态库·静态库·计算机组成原理·io操作
Yue丶越33 分钟前
【C语言】动态内存管理
c语言·开发语言
Edward1111111135 分钟前
普通java项目转为maven项目 J文件后缀.java变C文件
java·开发语言·maven
赵谨言35 分钟前
基于OpenCV的图像梯度与边缘检测研究
大数据·开发语言·经验分享·python