Thread线程学习(3) 了解Linux线程中的pthread_cancel()函数

news2024/9/21 0:52:01

目录

一、了解pthread_cancel()函数

二、使用pthread_cancel()函数的基础示例

三、使用pthread_cancel()函数取消线程的进阶示例

(1) 注意事项

(2) 进阶示例

四、pthread_cancel()函数的扩展内容

(1) 如何定义取消点:

(2) 使用pthread_cancel()函数需要谨慎操作,遵循以下几点:

四、总结


        在Linux系统中,线程是一种轻量级的执行单元,它允许程序在同一进程内同时执行多个任务。然而,在某些情况下,我们可能需要在程序运行过程中取消某个线程的执行。本篇文章将介绍pthread_cancel()函数,该函数用于取消一个正在执行的线程,并通过实例来说明其使用方法。

一、了解pthread_cancel()函数

        pthread_cancel()函数是Linux系统中用于取消线程执行的函数,其原型如下:

#include <pthread.h>

int pthread_cancel(pthread_t thread);

        该函数接受一个pthread_t类型的参数thread,用于指定要取消的线程。成功取消线程时,函数返回0;否则返回非0值。调用pthread_cancel()函数后,目标线程将收到一个取消请求,然后可以在合适的时机退出线程执行。

二、使用pthread_cancel()函数的基础示例

        下面通过一个示例来演示如何使用pthread_cancel()函数取消一个线程。

#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>

void* thread_func(void* arg)
{
    int count = 0;
     while (1) {
        printf("Thread is running, count: %d\n", count);
        count++;
        sleep(1);
    }
    // 检查取消请求
	pthread_testcancel();
	printf("Thread cancellation requested. Exiting...\n");
	pthread_exit(NULL);
    return NULL;
}
int main()
{
    pthread_t thread;
    // 创建线程
    pthread_create(&thread, NULL, thread_func, NULL);
    // 等待一段时间
    sleep(3);
    // 取消线程执行
    pthread_cancel(thread);
    // 等待线程退出
    pthread_join(thread, NULL);
    printf("Thread canceled successfully.\n");
    return 0;
}

运行结果如下:

开始运行...

Thread is running, count: 0
Thread is running, count: 1
Thread is running, count: 2
Thread is running, count: 3
Thread canceled successfully.

运行结束。

代码的主要逻辑如下:

  1. main() 函数中,我们创建了一个子线程 thread,并将其执行函数设置为 thread_func

  2. thread_func 是子线程的执行函数。在该函数中,我们使用一个循环来模拟线程的工作,每秒打印一次计数值 count。这个循环会一直执行,直到收到取消请求。

  3. 在主线程中,我们使用 sleep(3) 等待了3秒,然后调用 pthread_cancel(thread) 来发送取消请求给子线程。

  4. 接着,我们使用 pthread_join(thread, NULL) 等待子线程退出。这样,主线程会阻塞直到子线程执行完毕。

  5. 最后,主线程输出 "Thread canceled successfully." 表示线程成功被取消。

        在运行该代码时,你会看到子线程每秒打印一次计数值,而主线程在等待3秒后取消子线程的执行。子线程收到取消请求后,输出相应的消息并退出。最后,主线程输出线程取消成功的消息。

        请注意,使用 pthread_cancel() 函数来取消线程需要小心处理,确保线程在被取消之前完成必要的清理工作,以避免资源泄漏或数据不一致的问题。在这个例子中,我们在子线程中使用 pthread_testcancel() 来检查取消请求,以确保在取消点处退出线程。

三、使用pthread_cancel()函数取消线程的进阶示例

(1) 注意事项

在使用pthread_cancel()函数取消线程之前,需要注意以下几点:

1.确保线程可以被取消:线程需要以可取消的状态运行,即需要在创建线程时设置线程的取消状态为可取消,可以通过以下方式实现:

// 设置线程的取消状态为可取消
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

2.设置取消类型:线程的取消类型决定了线程被取消时的行为。可以通过以下方式设置取消类型:

// 设置线程的取消类型为延迟取消
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

常见的取消类型有PTHREAD_CANCEL_DEFERRED(线程取消在下一个取消点生效)和PTHREAD_CANCEL_ASYNCHRONOUS(立即取消线程)。

3.定义取消点:取消点是指程序中的某个位置,在该位置线程可以被取消。常见的取消点包括线程阻塞在I/O操作、休眠、等待锁等地方。

一旦线程符合上述要求,我们可以使用pthread_cancel()函数来取消线程。在主线程中调用pthread_cancel()函数,并传递要取消的线程标识符作为参数即可。例如:

// 其中thread_id为要取消的线程的标识符。
pthread_cancel(thread_id);

(2) 进阶示例

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>

void* thread_function(void* arg) {
    printf("子线程开始执行\n");   
    // 设置线程的取消状态为可取消
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 
    // 设置线程的取消类型为延迟取消
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
    while(1) {
        printf("子线程执行中...\n");
        sleep(1);
    }   
    printf("子线程执行完毕\n");
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    int res;  
    // 创建子线程
    res = pthread_create(&thread, NULL, thread_function, NULL);
    if (res != 0) {
        perror("线程创建失败");
        exit(EXIT_FAILURE);
    }   
    sleep(3);   
    // 取消子线程
    res = pthread_cancel(thread);
    if (res != 0) {
        perror("线程取消失败");
        exit(EXIT_FAILURE);
    }  
    // 等待子线程结束
    res = pthread_join(thread, NULL);
    if (res != 0) {
        perror("线程等待失败");
        exit(EXIT_FAILURE);
    }  
    printf("主线程执行完毕\n");  
    return 0;
}

运行结果如下:

开始运行...

子线程开始执行
子线程执行中...
子线程执行中...
子线程执行中...
子线程执行中...
主线程执行完毕

运行结束。

        在该示例代码中,我们创建了一个子线程,并在子线程中循环打印信息。主线程等待3秒后,通过调用pthread_cancel()函数来取消子线程的执行。子线程在每次循环中都会检查是否收到取消请求,由于我们将取消类型设置为延迟取消,所以子线程会在下一个取消点处取消。

        注意,在子线程中,我们使用pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)将线程的取消状态设置为可取消,以及使用pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)将线程的取消类型设置为延迟取消。

        运行以上代码,你将会看到子线程开始执行并不断打印信息,而在主线程中调用pthread_cancel()函数后,子线程会在下一个取消点处被取消,并输出"子线程执行完毕"。最后,主线程输出"主线程执行完毕",程序正常结束。

        请注意,实际的取消点取决于代码的具体情况,例如在阻塞I/O操作或调用特定函数时可能会有取消点。在实际的应用中,请确保你的代码中存在适当的取消点,以便能够及时响应取消请求。

四、pthread_cancel()函数的扩展内容

(1) 如何定义取消点:

取消点是指程序中的某个位置,在该位置线程可以被取消。为了定义取消点,我们可以使用以下方法:

  1. 阻塞式I/O操作:在进行阻塞式I/O操作时,线程会等待I/O完成,此时可以将这个等待过程作为取消点。例如,使用read()、write()或者select()等函数进行文件读写或网络通信时,这些函数在等待I/O完成时可以作为取消点。

  2. 线程休眠:线程调用休眠函数(如sleep()、usleep())时,线程会进入休眠状态,这个休眠过程可以作为取消点。

  3. 等待互斥锁:当线程在等待一个互斥锁时,可以将等待互斥锁的过程设置为取消点。在等待期间,线程会暂时挂起,等待其他线程释放互斥锁。

  4. 等待条件变量:当线程在等待条件变量满足条件时,可以将等待条件变量的过程设置为取消点。线程在等待期间会暂时挂起,等待其他线程发送信号满足条件。

  5. pthread_testcancel()函数:该函数是一个特殊的取消点定义方式,可以手动在代码中插入pthread_testcancel()函数,用于检测取消请求。如果有取消请求存在,该函数会立即取消线程。

在使用取消点时,需要注意以下几点:

  • 取消点的设置应该合理,以保证线程的安全性和数据一致性。取消点的位置应该在合适的地方,避免在关键代码段或者临界区内设置取消点。

  • 取消点的位置应该满足业务逻辑的要求,避免在一个关键操作前或后设置取消点,以免导致数据不一致或者程序逻辑错误。

  • 在设计多线程程序时,应该充分考虑取消点的位置和取消操作,保证程序的正确性和可维护性。

通过合理设置取消点,我们可以在需要的时候取消线程,实现更加灵活和可控的多线程编程。

(2) 使用pthread_cancel()函数需要谨慎操作,遵循以下几点:

使用pthread_cancel()函数需要谨慎操作,遵循以下几点:

  1. 在设计线程时,应该考虑线程的取消情况,并合理设置取消点,以保证线程的安全性和数据一致性。

  2. 取消一个线程时,应该确保线程在被取消前已经完成了必要的清理工作,例如释放动态分配的内存、关闭打开的文件等。

  3. 注意处理线程取消的返回值。如果pthread_cancel()函数返回0,表示成功发送取消请求,但并不代表线程立即终止。可以使用pthread_join()函数等待线程终止,并获取线程的返回值。

四、总结

         本文深入介绍了Linux线程的pthread_cancel()函数,该函数可以用于取消一个正在执行的线程。在使用pthread_cancel()函数时,需要合理设置线程的取消状态和取消类型,并确保线程在取消前完成必要的清理工作。同时,对于取消操作的返回值需要进行适当处理。合理使用pthread_cancel()函数可以帮助我们实现更加灵活和可控的多线程编程。

 笔记分享,如有误感谢指教;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/536409.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电极法测污水常规五参数(PH、电导率、溶解氧、温度、浊度)

检测水质常规五参数的意义&#xff1a; pH&#xff1a;地表水水质中pH值的变化会影响藻类对氧气的摄入能力及动物对食物的摄取敏感度&#xff1b; 电导率&#xff1a;主要是测水的导电性&#xff0c;监测水体中总的离子浓度。包含了各种化学物质、重金属、杂质等等各种导电性物…

vue+elementui+nodejs校园生活信息服务快递系统v62911

语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;VScode 学生登录&#xff0c;学生通过填写用户名、密码、权限等信息&#xff0c;输入完成后选择登录即可进入校园快领服务系统 学生登录进入校…

ESP32-C2系列开发板简介

C2是一个芯片采用4毫米x 4毫米封装&#xff0c;与272 kB内存。它运行框架&#xff0c;例如ESP-Jumpstart和ESP造雨者&#xff0c;同时它也运行ESP-IDF。ESP-IDF是Espressif面向嵌入式物联网设备的开源实时操作系统&#xff0c;受到了全球用户的信赖。它由支持Espressif以及所有…

阿里P6经验分享,这8种不同类型的自动化测试框架,你会吗?

以下为作者观点&#xff1a; 在自动化测试中&#xff0c;框架提供了一种组织和执行测试案例的结构化方式。它们提供了一套准则和最佳实践&#xff0c;使测试人员能够编写可重复使用、可维护和可扩展的测试脚本。在这篇文章中&#xff0c;我们将讨论自动化测试中不同类型的框架…

最近火起的 Bean Searcher 与 MyBatis Plus 到底有啥区别?

专属小彩蛋&#xff1a;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff08;前言 - 床长人工智能教程&#xff09; 福利&#xff1a;taobao扫码赚个零花钱~ Bean Searcher 号称 任…

使用Python爬取给定网页的所有链接(附完整代码)

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 此脚本从给定的网页中…

C++基础讲解第五期(继承、多继承、虚继承、向上转型、同名函数)

C基础讲解第五期 代码中也有对应知识注释&#xff0c;别忘看&#xff0c;一起学习&#xff01; 一、继承&#xff08;接第四期&#xff09;1. const修饰成员函数2. 同名函数3. 继承中的static关键字4. 继承中类型兼容性原则5. 多继承(使用参数初始化列表&#xff09;&#xff0…

SDN控制器三平面(软件定义网络、OOB)

又名 软件定义网络 软件定义网络SDN(Software Defined Network)是由美国斯坦福大学CLean Slate研究组提出的一种新型网络创新架构,可通过软件编程的形式定义和控制网络,其控制平面和转发平面分离及开放性可编程的特点,被认为是网络领域的一场革命,为新型互联网体系结…

Gitlab----基于Kubernetes安装Gitlab

【原文链接】Gitlab----基于Kubernetes安装Gitlab &#xff08;1&#xff09;创建命名空间gitlba kubectl create namespace gitlab&#xff08;2&#xff09;然后创建Gitlab用的PVC&#xff0c;编写yaml配置文件如下 kind: PersistentVolumeClaim apiVersion: v1 metadata:…

002 - STM32固件库GPIO(一)操作LED灯

STM32固件库操作LED灯 1、创建板级支持包文件 在User目录下创建LED文件夹&#xff0c;包含bsp_led.c及头文件bsp_led.h&#xff0c;之后在Keil中将bsp_led.c加入 2、程序代码 bsp_led.c #include ".\LED\bsp_led.h" //相对路径访问&#xff0c;可以在工程配置内…

LeetCode 199. 二叉树的右视图

199. 二叉树的右视图 描述 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 示例1 输入&#xff1a;[1,2,3,null,5,null,4] 输出&#xff1a;[1,3,4] 示例2 输入&#xf…

【笔试强训选择题】Day14.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目录…

Linux环境搭建与历史

目录 前言 1.操作系统是什么 2. 为什么我们要选择Linux 3.Linux操作系统发展历史 4.企业应用现状 Linux在服务器领域的发展 Linux在桌面领域的发展 Linux在移动嵌入式领域的发展 Linux在云计算/大数据领域的发展 5.发行版本 6. Linux环境配置 6.1 Linux搭建的方式 …

程序员挣够了钱,到中年你还害怕失业吗?

最近一刷知乎全部都是大龄程序员失业危机 真的有这么可怕吗&#xff1f; 程序员35岁就真的到了瓶颈期&#xff1f; 我不这么认为 挣够了钱&#xff0c;当然不可怕&#xff0c;问题是没挣够啊~&#xff01;&#xff01;&#xff01; 按题主的算法是&#xff0c;大城市薪资1…

C++基础STL-map容器

map容器介绍&#xff1a; 作为关联式容器的一种&#xff0c;map 容器存储的都是 pair 对象&#xff0c;也就是用 pair 类模板创建的键值对。其中&#xff0c;各个键值对的键和值可以是任意数据类型&#xff0c;包括 C基本数据类型&#xff08;int、double 等&#xff0…

快速入门matlab——变量练习

学习目标&#xff1a;1.掌握matlab编程中最常用的几种变量类型 2.对变量类型的属性有所熟悉&#xff0c;不要求记忆&#xff0c;知道了解即可 3.要求熟练运用这几种变量类型创建自己的变量 clear all; % 清除Workspace中的所有…

服务网格:优化微服务通信与保障系统安全性的架构利器

文章目录 服务网格&#xff1a;优化微服务通信与保障系统安全性的架构利器1. 什么是服务网格&#xff1f;微服务架构概述&#xff1a;服务网格的定义和作用&#xff1a; 2. 服务网格的特点&#xff1a;透明性&#xff1a;无需修改应用代码服务发现与负载均衡&#xff1a;动态发…

GPT3.5 VS GPT-4写领导讲话稿,谁是最强笔杆子?

正文共 1240 字&#xff0c;阅读大约需要 5 分钟 文秘/公务员必备技巧&#xff0c;您将在5分钟后获得以下超能力&#xff1a; 快速生成领导讲话稿 Beezy评级 &#xff1a;B级 *经过简单的寻找&#xff0c; 大部分人能立刻掌握。主要节省时间。 推荐人 | Kim 编辑者 | Linda ●…

redis持久化配置

回顾&#xff1a;rpcbind111 nfs2049 redis高可用高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务&#xff08;99.9%&#xff0c;99.99%&#xff0c;99.999%等&#xff09; 还要考虑提供主从分离&#xff0c;快速容灾技术&#…

在 React 中使用 highlight.js 和 Clipboard.js 实现代码块和复制功能

参考链接&#xff1a;https://blog.csdn.net/huangjuan0229/article/details/130319050 在前端开发中&#xff0c;代码块高亮和复制功能是十分常见的需求。而在 React 中&#xff0c;常用的代码高亮库是 highlight.js&#xff0c;常用的复制库是 Clipboard.js。本篇文章将介绍…