pthread_cleanup_push与pthread_cleanup_pop的目的(作用)

2024-05-07 05:18

本文主要是介绍pthread_cleanup_push与pthread_cleanup_pop的目的(作用),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

比如thread1:
执行
pthread_mutex_lock(&mutex);

//一些会阻塞程序运行的调用,比如套接字的accept,等待客户连接
sock = accept(……); //这里是随便找的一个可以阻塞的接口

pthread_mutex_unlock(&mutex);
这个例子中,如果线程1执行accept时,线程会阻塞(也就是等在那里,有客户端连接的时候才返回,或则出现其他故障),线程等待中……

这时候线程2发现线程1等了很久,不赖烦了,他想关掉线程1,于是调用pthread_cancel()或者类似函数,请求线程1立即退出。

这时候线程1仍然在accept等待中,当它收到线程2的cancel信号后,就会从accept中退出,然后终止线程,注意这个时候线程1还没有执行:
pthread_mutex_unlock(&mutex);
也就是说锁资源没有释放,这回造成其他线程的死锁问题。

所以必须在线程接收到cancel后用一种方法来保证异常退出(也就是线程没达到终点)时可以做清理工作(主要是解锁方面),pthread_cleanup_push与pthread_cleanup_pop就是这样的。

pthread_cleanup_push(some_clean_func,…)
pthread_mutex_lock(&mutex);

//一些会阻塞程序运行的调用,比如套接字的accept,等待客户连接
sock = accept(……); //这里是随便找的一个可以阻塞的接口

pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(0);
return NULL;
上面的代码,如果accept被cancel后线程退出,会自动调用some_clean_func函数,在这个函数中你可以释放锁资源。如果accept没有被cancel,那么线程继续执行,当pthread_mutex_unlock(&mutex);表示线程自己正确的释放资源了,而执行pthread_cleanup_pop(0);也就是取消掉前面的some_clean_func函数。接着return线程就正确的结束了。

不晓得你明白没,通俗点就是:
pthread_cleanup_push注册一个回调函数,如果你的线程在对应的pthread_cleanup_pop之前异常退出(return是正常退出,其他是异常),那么系统就会执行这个回调函数(回调函数要做什么你自己决定)。但是如果在pthread_cleanup_pop之前没有异常退出,pthread_cleanup_pop就把对应的回调函数取消了,

关于取消点的解释:

比如你执行:
printf(“thread sleep\n”);
sleep(10);
printf(“thread wake…\n”);
在sleep函数中,线程睡眠,结果收到cancel信号,这时候线程从sleep中醒来,但是线程不会立刻退出。这是因为pthread与C库方面的原因(具体是啥我也不清楚),pthread的建议是,如果一个函数是阻塞的,那么你必须在这个函数前后建立取消点,比如:
printf(“thread sleep\n”);
pthread_testcancel();
sleep(10);
pthread_testcancel();
printf(“thread wake…\n”);
这样,就添加了两个取消掉。在执行到pthread_testcancel的位置时,线程才可能响应cancel退出进程。

额外的知识:

对于cancel信号,线程有两种方法: 忽略,和响应。默认是响应
接收到cancel信号,线程有两种处理类型: 立即响应 和 延迟响应(在最近的取消点响应),默认是延迟响应

这篇关于pthread_cleanup_push与pthread_cleanup_pop的目的(作用)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

python常用的正则表达式及作用

《python常用的正则表达式及作用》正则表达式是处理字符串的强大工具,Python通过re模块提供正则表达式支持,本文给大家介绍python常用的正则表达式及作用详解,感兴趣的朋友跟随小编一起看看吧... 目录python常用正则表达式及作用基本匹配模式常用正则表达式示例常用量词边界匹配分组和捕获常用re

Java 继承和多态的作用及好处

《Java继承和多态的作用及好处》文章讲解Java继承与多态的概念、语法及应用,继承通过extends复用父类成员,减少冗余;多态实现方法重写与向上转型,提升灵活性与代码复用性,动态绑定降低圈复杂度... 目录1. 继承1.1 什么是继承1.2 继承的作用和好处1.3 继承的语法1.4 子类访问父类里面的成

SpringBoot 中 CommandLineRunner的作用示例详解

《SpringBoot中CommandLineRunner的作用示例详解》SpringBoot提供的一种简单的实现方案就是添加一个model并实现CommandLineRunner接口,实现功能的... 目录1、CommandLineRunnerSpringBoot中CommandLineRunner的作用

$在R语言中的作用示例小结

《$在R语言中的作用示例小结》在R语言中,$是一个非常重要的操作符,主要用于访问对象的成员或组件,它的用途非常广泛,不仅限于数据框(dataframe),还可以用于列表(list)、环境(enviro... 目录1. 访问数据框(data frame)中的列2. 访问列表(list)中的元素3. 访问jav

Kotlin运算符重载函数及作用场景

《Kotlin运算符重载函数及作用场景》在Kotlin里,运算符重载函数允许为自定义类型重新定义现有的运算符(如+-…)行为,从而让自定义类型能像内置类型那样使用运算符,本文给大家介绍Kotlin运算... 目录基本语法作用场景类对象数据类型接口注意事项在 Kotlin 里,运算符重载函数允许为自定义类型重

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa