5.pthread_join/pthread_exit的用法解析

2024-05-30 20:48
文章标签 用法 解析 join exit pthread

本文主要是介绍5.pthread_join/pthread_exit的用法解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

官方说法:

函数pthread_join用来等待一个线程的结束。函数原型为:

  extern int pthread_join __P ((pthread_t __th, void **__thread_return));

  第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的线程将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;

另一种方式是通过函数pthread_exit来实现。它的函数原型为:

  extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));

  唯一的参数是函数的返回代码,只要pthread_exit中的参数retval不是NULL,这个值将被传递给 thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。


上面说的有点乱,看不懂的看这里:

pthread_join用于等待一个线程的结束,也就是主线程中要是加了这段代码,就会在加代码的位置卡主,直到这个线程执行完毕才往下走。

pthread_exit用于强制退出一个线程(非执行完毕退出),一般用于线程内部。


结合用法:

一般都是pthread_exit在线程内退出,然后返回一个值。这个时候就跳到主线程的pthread_join了(因为一直在等你结束),这个返回值会直接送到pthread_join,实现了主与分线程的通信。


注意事项:

这个线程退出的返回值的格式是void*,无论是什么格式都要强转成void*才能返回出来主线程(pthread_exit((void*)tmp);),而这个时候pthread_join就去接这个值,我们传进去一个void*的地址也就是&(void*),传地址进去接值是接口类函数常用的做法,有同样效果的做法是引用&,但是这个做法一来值容易被误改,二来不规范,所以定义一个类型然后把地址传进去修改value。回到题目,这里返回的void*是一个指针类型,必须强转成对应的指针才能用。

举个例子,如果是char* = “mimida”;传出来的tmp,必须(char*)tmp一下。

而如果是int* a = new(3888);这种类型返回的tmp,必须*(int*)tmp一下才能用。

最重要的一点,你定义的类型和最后出来的类型一定要一致,不然很容易出现问题。也就是你定义了int*,最后强转出来的一定是*(int*)。

别void* a = (void*)10;这种诡异的格式(我就中过招),一开始是什么就转成什么!(这个规则同时也适用于线程数据里的set和get)


实例如下:

[cpp]  view plain copy
  1.                        <pre name="code" class="cpp">/* example.c*/  
  2.   
  3. #include <stdio.h>  
  4.   
  5. #include <pthread.h>  
  6.   
  7. void thread1(char s[])  
  8. {   
  9.         printf("This is a pthread1.\n");  
  10.         printf("%s\n",s);  
  11.         pthread_exit((void*)"the first return!");  //结束线程,返回一个值。  
  12. }  
  13. void thread2(char s[])  
  14. {  
  15.         int *a = new(46666);  
  16. <span style="white-space:pre">    </span>printf("This is a pthread2.\n");  
  17.         printf("%s\n",s);  
  18.         pthread_exit((void*)a);  
  19. }  
  20.   
  21. /**************main function ****************/  
  22.   
  23. int main(void)  
  24.   
  25.   
  26. {  
  27.         pthread_t id1,id2;  
  28.         void *a1,*a2;  
  29.         int i,ret1,ret2;  
  30.         char s1[]="This is first thread!";  
  31.         char s2[]="This is second thread!";  
  32.         ret1=pthread_create(&id1,NULL,(void *) thread1,s1);  
  33.   
  34.         ret2=pthread_create(&id2,NULL,(void *) thread2,s2);  
  35.   
  36.         if(ret1!=0){  
  37.                 printf ("Create pthread1 error!\n");  
  38.                 exit (1);  
  39.         }  
  40.         pthread_join(id1,&a1);  
  41.   
  42.         printf("%s\n",(char*)a1);  
  43.   
  44.         if(ret2!=0){  
  45.                 printf ("Create pthread2 error!\n");  
  46.                 exit (1);  
  47.         }  
  48.         printf("This is the  main process.\n");  
  49.         pthread_join(id2,&a2);  
  50.         printf("%s\n",*(int*)a2);  
  51.         return (0);  
  52.   
  53. }    

 

运行结果: 
[****@XD**** c]$ ./example 
This is a pthread1. 
This is first thread! 

the first return!
This is the main process. 
This is a pthread2. 
This is second thread! 

46666

这篇关于5.pthread_join/pthread_exit的用法解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1016863

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

SpringBoot 获取请求参数的常用注解及用法

《SpringBoot获取请求参数的常用注解及用法》SpringBoot通过@RequestParam、@PathVariable等注解支持从HTTP请求中获取参数,涵盖查询、路径、请求体、头、C... 目录SpringBoot 提供了多种注解来方便地从 HTTP 请求中获取参数以下是主要的注解及其用法:1

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

Java中HashMap的用法详细介绍

《Java中HashMap的用法详细介绍》JavaHashMap是一种高效的数据结构,用于存储键值对,它是基于哈希表实现的,提供快速的插入、删除和查找操作,:本文主要介绍Java中HashMap... 目录一.HashMap1.基本概念2.底层数据结构:3.HashCode和equals方法为什么重写Has

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手