Linux线程的创建和取消

本文介绍了线程创建与取消的相关函数接口及使用要点,包括pthread_create和pthread_cancel等关键API,并通过示例代码演示如何实现线程的安全取消机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 线程创建和取消函数接口

线程创建的函数原型:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

thread参数:新线程的TID

attr参数:线程属性

start_routine参数:线程例程,也就是如果线程创建成功,线程立即去执行的函数

arg参数:线程例程的参数

对线程创建函数的使用需要注意以下几点:

  • 线程例程指的是:线程创建成功后线程立即执行的函数
  • POSIX线程库的所有API对返回值的处理原则是一致的:成功返回0,失败返回错误码errno
  • 线程属性如果设置为NULL,则会创建一个标准属性的线程

线程取消的函数原型:

int pthread_cancel(pthread_t thread);

thread参数:线程TID

当线程互道一个取消请求时,它将会如何表现取决于两点:1. 线程当前的取消状态 2. 线程当前的取消类型

  • 线程当前的取消状态:一种是PTHREAD_CANCEL_ENABLE,该状态是线程默认的,表示线程可以接受取消请求。另一种是PTHREAD_CANCEL_DISABLE,该状态表示关闭取消请求,不对其响应
  • 线程当前的取消类型:在线程接受取消请求的情况下,线程如何停下来取决于两种不同的响应取消类型,一种是PTHREAD_CANCEL_DEFERRED,表示延迟响应。另一种是PTHREAD_CANCEL_ASYNCHRONOUS,表示立即响应

压栈或弹栈线程的取消处理的函数原型:
 由于线程在任何时刻都有可能持有互斥锁,信号量等资源,一旦被取消很可能导致别的线程死锁,因此如果一条线程的确可以取消,那么在该线程被取消之前必须使用相应的API函数来为将来可能出现的取消请求注册“处理例程”,让这些例程自动释放持有的资源

void pthread_cleanup_push(void (*routine)(void *),void *arg);

routine 参数:线程的取消处理例程

arg 参数:储存线程退出值的内存指针

void pthread_cleanup_pop(int execute);

execute 参数:如果是0,弹栈线程的取消处理例程,但不执行该例程;如果非0,弹栈线程的取消处理例程,并执行该例程

压栈或弹栈线程的取消处理的函数的使用需要注意以下几点:

  • 使用pthread_cleanup_push()可以为线程的取消请求压入多个处理例程,这些例程会以栈的形式保留起来,在线程被取消之后,它们可以以弹栈的后进先出的形式依次被执行
  • pthread_cleanup_push()和pthread_cleanup_pop()这两个函数必须配套使用,而且必须出现在同一层代码块种

2. 线程创建和取消代码示例

以下代码展示了如何创建一个线程,以及该线程如何正确地处理该取消请求

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

pthread_mutex_t m;      //线程锁

void handler(void *args){
    pthread_mutex_unlock(&m);   //解锁
}

void * routine(void *args){ //线程例程

    //加锁前,将handler压入线程取消处理例程的栈中,以防中途被取消。如果中途被取消,执行handler
    pthread_cleanup_push(handler, NULL);
    pthread_mutex_lock(&m);
    printf("[%u]:[%s] abtained the mutex\n", (unsigned)pthread_self(), __FUNCTION__);

    sleep(10);  //在此线程睡眠期间如果收到取消请求,则handler被执行

    //解锁后,将handler弹出来,但并不执行它
    pthread_mutex_unlock(&m);
    pthread_cleanup_pop(0);

    //线程退出
    pthread_exit(NULL);
}

int main(int argc, char**argv){
    pthread_mutex_init(&m, NULL);   //初始化线程锁
    
    //创建线程,并让线程执行例程
    pthread_t tid;
    pthread_create(&tid, NULL, routine, NULL);
    
    //等待1秒后,向子线程发送一个取消请求
    sleep(1);
    pthread_cancel(tid);
    
    //此时子线程被取消了,但被handler自动释放,因此主线程可以加锁
    pthread_mutex_lock(&m);
    printf("[%u]:[%s] abtained the mutex\n", (unsigned)pthread_self(), __FUNCTION__);
    pthread_mutex_unlock(&m);
    return 0;
}

执行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

博可睿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值