C语言如何正确的终止正在运行的子线程

yizhihongxing

C语言中,终止正在运行的子线程有两种常用方法:一种是让线程函数正常返回;另一种是使用pthread_cancel函数强制终止线程。我们来分别介绍这两种方法的具体实现。

方法一

让子线程函数正常返回,从而终止子线程的执行。这种方式需要在线程函数中判断是否需要退出,并在需要退出时,将线程函数的返回值设为0。线程启动时,使用pthread_create函数创建线程,并将线程ID存储在一个全局变量中,以便在需要终止线程时调用pthread_cancel函数。

下面是一个示例代码,使用while循环不断执行某些任务,在接收信号后退出线程:

#include <stdio.h>
#include <pthread.h>
#include <signal.h>

pthread_t tid;

void signal_handler(int sig) {
    if (sig == SIGINT) {
        printf("SIGINT received, canceling thread...\n");
        pthread_cancel(tid);
    }
}

void *thread_func(void *arg) {
    int count = 0;
    while (1) {
        printf("Task %d is running...\n", count++);
        sleep(1);
    }
    return NULL; // 线程函数返回值为NULL,表示正常退出
}

int main() {
    signal(SIGINT, signal_handler);
    pthread_create(&tid, NULL, thread_func, NULL);
    pthread_join(tid, NULL); //等待线程结束,这行就是可有可无的,其实加上这行,只是为了好看
    return 0;
}

不断输出任务,并在接收信号后退出线程,注意:有一个重要的点,在主线程中需要调用pthread_join函数,等待子线程结束,这样才能使子线程占用的资源被正确释放。如果不等待子线程结束而直接返回,子线程就会成为“僵尸线程”,占用系统资源。

方法二

使用pthread_cancel函数强制终止子线程的执行。pthread_cancel函数调用后,线程会收到一个取消请求,可以使用pthread_setcancelstate函数在线程函数中判断是否接收到了取消请求,并进行相应的处理。

下面是一个示例代码,使用while循环不断执行某些任务,在接收信号后强制终止线程:

#include <stdio.h>
#include <pthread.h>
#include <signal.h>

pthread_t tid;

void signal_handler(int sig) {
    if (sig == SIGINT) {
        printf("SIGINT received, canceling thread...\n");
        pthread_cancel(tid);
    }
}

void *thread_func(void *arg) {
    int cancel_state;
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); // 允许取消

    while (1) {
        pthread_testcancel(); // 检查是否接收到取消请求,如果是则终止线程
        printf("Task is running...\n");
        sleep(1);
    }
    return NULL;
}

int main() {
    signal(SIGINT, signal_handler);
    pthread_create(&tid, NULL, thread_func, NULL);
    pthread_join(tid, NULL); // 等待线程结束

    return 0;
}

每次任务执行完成后,调用pthread_testcancel函数检查线程是否收到了取消请求。如果收到了,则线程通知取消,线程函数就会返回NULL。需要注意的是,即使线程通过pthread_testcancel函数检查取消请求时,没有收到取消请求,函数也会立刻返回。

参考文献:
- Linux系统编程
- POSIX多线程编程指南

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言如何正确的终止正在运行的子线程 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • IOS 开发之NSDictionary转换成JSON字符串

    我来为您详细讲解iOS开发中将NSDictionary转换为JSON字符串的完整攻略。 1. 转换原理 在iOS中,我们可以使用Apple官方提供的NSJSONSerialization类来实现NSDictionary转换成JSON字符串。具体来说,我们可以使用此类的dataWithJSONObject:options:error:方法将NSDictiona…

    C 2023年5月23日
    00
  • OpenCV使用邻居访问扫描图像的操作方法

    使用邻居访问扫描图像是计算机视觉和图像处理中常用的一种操作。OpenCV库中提供了许多函数和方法用于处理各种类型的图像。 以下是OpenCV使用邻居访问扫描图像的操作方法: 1. 定义邻居 邻居可以是指像素周围的像素或以像素为中心的矩形区域。在OpenCV中,我们可以使用函数 cv2.getStructuringElement() 来创建不同形状、尺寸和内核…

    C 2023年5月22日
    00
  • AJAX开发简略 (第二部分)

    下面我来详细讲解“AJAX开发简略 (第二部分)”的完整攻略。 AJAX开发简略(第二部分) 在上一篇文章中,我们已经了解到 AJAX 的定义、用途和基本的使用方法。本篇文章将介绍如何使用 AJAX 进行数据交互,以及如何避免常见的 AJAX 开发问题。 数据交互 AJAX 最常见的用途就是向服务器获取数据并更新页面,而且这个过程是异步进行,不会阻塞页面加载…

    C 2023年5月22日
    00
  • C语言使用函数实现字符串部分复制问题

    C语言使用函数实现字符串部分复制可以使用标准库函数strncpy()实现。strncpy()函数用于将源字符串的前n个字符复制到目标字符串中,当复制到字符串的末尾时,会在末尾自动添加’\0’。以下是实现字符串部分复制的步骤: 引入头文件 #include <string.h> 使用strncpy函数 char *strncpy(char *des…

    C 2023年5月23日
    00
  • C语言实现ATM系统程序的完整代码

    下面是C语言实现ATM系统程序的完整代码攻略,包括以下步骤: 确定实现ATM系统所需的功能和操作,例如登录、查询余额、取款、存款、转账等。 设计ATM系统的数据结构,包括记录用户信息的结构体、记录ATM机状态的结构体等。在这个实现中,我们可以采用一个用户信息的数据结构体,包含账户名、账户密码和账户余额等信息。对于ATM机状态,我们可以使用一个状态枚举变量,例…

    C 2023年5月23日
    00
  • C++使用easyx画实时走动的钟表

    C++是一种强大的编程语言,而easyx是一款很棒的图形库,可用于制作各种有趣的图形化应用程序。本文将为大家介绍如何使用C++和easyx画实时走动的钟表。 步骤一:准备工作 在开始之前,需要下载easyx图形库并安装。easyx官方网站提供了最新的安装程序,实际上安装很简单,只需双击运行安装程序即可完成安装。安装后,在Visual Studio中创建一个空…

    C 2023年5月23日
    00
  • 浅谈Linux系统中的异常堆栈跟踪的简单实现

    浅谈Linux系统中的异常堆栈跟踪的简单实现 什么是异常堆栈跟踪? 在Linux系统中,异常堆栈跟踪(Exception Stack Tracing)是一种找出内核空间代码异常的技术。当操作系统内核出现异常时,堆栈跟踪可以记录每个程序执行的位置,并以可视化的方式展示出来,帮助开发者快速定位和修复程序错误。 实现方法 异常堆栈跟踪的实现需要使用一些工具和技术。…

    C 2023年5月23日
    00
  • C语言return, exit, abort的区别

    C语言中return, exit, abort都是用来结束程序的函数,但是它们有一些区别。 return return语句是用来返回函数的返回值,并将函数的执行权交给调用者。如果在main函数中使用return语句,则相当于结束程序。return语句的作用范围仅限于函数内部,即return只能在函数中使用。 以下是return的示例代码: #include …

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部