pthread_join函数及linux线程

Pthread导致的memory leak 今天在解决客户的一个内存泄露的问题,客户提供了source code,但从代码语法,代码结构上的检查,都没有发现什么问题,编码风格还算整洁,那为什么还有Memory Leak?客户代码有一个特点,使用了多线程,而且用得还比较频繁,而且初看代码,也没有问题,线和有创建pthread_create, 都会有退出pthread_exit,那问题在那里,于是,就查看了下linux的api手册,仔细研究了下l 阅读详情

pthread_join函数及linux线程

pthread_join使一个线程等待另一个线程结束。

代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。

所有线程都有一个线程号,也就是Thread ID。其类型为pthread_t。通过调用pthread_self()函数可以获得自身的线程号。

下面说一下如何创建一个线程。

通过创建线程,线程将会执行一个线程函数,该线程格式必须按照下面来声明:

void * Thread_Function(void *)

创建线程的函数如下:
QUOTE:
int pthread_create(pthread_t *restrict thread,

const pthread_attr_t *restrict attr,

void *(*start_routine)(void*), void *restrict arg);

下面说明一下各个参数的含义:

thread:所创建的线程号。

attr:所创建的线程属性,这个将在后面详细说明。

start_routine:即将运行的线程函数。

art:传递给线程函数的参数。

下面是一个简单的创建线程例子:
QUOTE:
#include 

#include 



void* print_xs (void* unused)

{

while (1)

fputc (‘x’, stderr);

return NULL;

}



int main ()

{

pthread_t thread_id;



pthread_create (&thread_id, NULL, &print_xs, NULL);



while (1)

fputc (‘o’, stderr);

return 0;

}

在编译的时候需要注意,由于线程创建函数在libpthread.so库中,所以在编译命令中需要将该库导入。命令如下:

gcc –o createthread –lpthread createthread.c

如果想传递参数给线程函数,可以通过其参数arg,其类型是void *。如果你需要传递多个参数的话,可以考虑将这些参数组成一个结构体来传递。另外,由于类型是void *,所以你的参数不可以被提前释放掉。

下面一个问题和前面创建进程类似,不过带来的问题回避进程要严重得多。如果你的主线程,也就是main函数执行的那个线程,在你其他县城推出之前就已经退出,那么带来的bug则不可估量。通过pthread_join函数会让主线程阻塞,直到所有线程都已经退出。

int pthread_join(pthread_t thread, void **value_ptr);

thread:等待退出线程的线程号。

value_ptr:退出线程的返回值。

下面一个例子结合上面的内容:
QUOTE:
int main ()

{

pthread_t thread1_id;

pthread_t thread2_id;

struct char_print_parms thread1_args;

struct char_print_parms thread2_args;



thread1_args.character = ’x’;

thread1_args.count = 30000;

pthread_create (&thread1_id, NULL, &char_print, &thread1_args);



thread2_args.character = ’o’;

thread2_args.count = 20000;

pthread_create (&thread2_id, NULL, &char_print, &thread2_args);



pthread_join (thread1_id, NULL);



pthread_join (thread2_id, NULL);



return 0;

}

下面说一下前面提到的线程属性。

在我们前面提到,可以通过pthread_join()函数来使主线程阻塞等待其他线程退出,这样主线程可以清理其他线程的环境。但是还有一些线程,更喜欢自己来清理退出的状态,他们也不愿意主线程调用pthread_join来等待他们。我们将这一类线程的属性称为detached。如果我们在调用pthread_create()函数的时候将属性设置为NULL,则表明我们希望所创建的线程采用默认的属性,也就是jionable。如果需要将属性设置为detached,则参考下面的例子:
QUOTE:
#include 

#include 

void * start_run(void * arg)

{

//do some work

}

int main()

{

pthread_t thread_id;

pthread_attr_t attr;

pthread_attr_init(&attr);

pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

pthread_create(&thread_id,&attr,start_run,NULL);

pthread_attr_destroy(&attr);

sleep(5);

exit(0);

}

在线程设置为joinable后,可以调用pthread_detach()使之成为detached。但是相反的操作则不可以。还有,如果线程已经调用pthread_join()后,则再调用pthread_detach()则不会有任何效果。

线程可以通过自身执行结束来结束,也可以通过调用pthread_exit()来结束线程的执行。另外,线程甲可以被线程乙被动结束。这个通过调用pthread_cancel()来达到目的。

int pthread_cancel(pthread_t thread);

函数调用成功返回0。

当然,线程也不是被动的被别人结束。它可以通过设置自身的属性来决定如何结束。

线程的被动结束分为两种,一种是异步终结,另外一种是同步终结。异步终结就是当其他线程调用pthread_cancel的时候,线程就立刻被结束。而同步终结则不会立刻终结,它会继续运行,直到到达下一个结束点(cancellation point)。当一个线程被按照默认的创建方式创建,那么它的属性是同步终结。

通过调用pthread_setcanceltype()来设置终结状态。

int pthread_setcanceltype(int type, int *oldtype);

state:要设置的状态,可以为PTHREAD_CANCEL_DEFERRED或者为PTHREAD_CANCEL_ASYNCHRONOUS。

那么前面提到的结束点又是如何设置了?最常用的创建终结点就是调用pthread_testcancel()的地方。该函数除了检查同步终结时的状态,其他什么也不做。

上面一个函数是用来设置终结状态的。还可以通过下面的函数来设置终结类型,即该线程可不可以被终结:

int pthread_setcancelstate(int state, int *oldstate);

state:终结状态,可以为PTHREAD_CANCEL_DISABLE或者PTHREAD_CANCEL_ENABLE。具体什么含义大家可以通过单词意思即可明白。

最后说一下线程的本质。其实在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone()。该系统copy了一个和原先进程完全一样的进程,并在这个进程中执行线程函数。不过这个copy过程和fork不一样。copy后的进程和原先的进程共享了所有的变量,运行环境。这样,原先进程中的变量变动在copy后的进程中便能体现出来。
Linux线程全面解析:pthread_create、pthread_join等函数详解与应用 线程安全指多线程环境下数据访问的一致性保证方法:互斥锁、原子操作、线程局部存储、不可变对象。 阅读详情

相关推荐

Linux pthread_join()函数使用总结

pthread_join()函数原型: int pthread_join(pthread_t thread, void **retval); 参数说明args: pthread_t thread: 被连接线程的线程号 void **retval : 指向一个指向被连接线程的返回码的指针的指针 return: 线程连接的状态,0是成功,非0是失败 当调用 pthread_join() 时,当前线程会处于阻塞状态,直到被调用的线程结束后,当前线程才会重...

程序猿老樊的博客 5382

pthread_join()详解及实验

pthread_join()函数原型: int pthread_join(pthread_t thread, void **retval); args: pthread_t thread: 被连接线程的线程号 void **retval : 指向一个指向被连接线程的返回码的指针的指针 return: 线程连接的状态,0是成功,非0是失败 1.为什么要使用pthread...

EmbeddedCoder 的优快云博客 3万+

Linux进阶:深入理解pthread_join函数及其在嵌入式系统中的应用

通过等待指定线程的结束,并获取其返回值,我们可以实现线程的同步和协作。在嵌入式系统中,pthread_join函数发挥了重要的作用,帮助我们合理管理线程和资源。pthread_join函数是Linux操作系统提供的线程管理函数之一,它的作用是等待一个线程的结束,并回收其资源。在上述示例代码中,我们首先创建了两个线程,一个负责填充数组,另一个负责计算数组的和。pthread_join函数的功能是等待指定的线程终止,并获取线程的返回值。通过等待其他线程的结束,并获取其返回值,可以实现线程之间的数据共享和协作。

CodeSageX的博客 311

pthread_join()函数

再次强调,一个线程执行结束的返回值只能由一个 pthread_join() 函数获取,当有多个线程调用 pthread_join() 函数获取同一个线程的执行结果时,哪个线程最先执行 pthread_join() 函数,执行结果就由那个线程获得,其它线程的 pthread_join() 函数都将执行失败。在应用中,用pthread_join()函数控制线程的执行流,阻塞调用它的线程,直至目标线程执行结束(接收到目标线程的返回值),阻塞状态才会解除。》一节中做详细讲解。还有一个作用是:获取线程的返回值。

玖玖玖 5035

Linux中pthread_create、pthread_join函数与线程销毁的详细解析

Linux中pthread_create、pthread_join函数与线程销毁的详细解析

a_zxswer的博客 760

法兰克仿真软件FANUC CNC Guide v25.0 安装教程及中文设置

下载地址在文末。我们公司用新到一批FANUC 系统的设备,为方便使用就装了一个 FANUC 数控系统仿真软件FANUC CNC Guide v25.0 ,还是最新版不是市面上流传的老版本。模拟学习一下。

hakesashou的博客 1万+

linux下的线程创建相关API函数(pthread _create、pthread _join、pthread _detach、pthread _concel、pthread _kill)

linux下的线程创建以及线程通讯相关API函数线程创建相关API函数pthread _create(创建线程函数)1. 头文件2. 函数原型3. 参数说明4. 返回值:5. 举例说明:6、传递不同参数pthread_join()1. 含义2. 背景3. 函数原型4. 第二个参数说明5. 终止状态(线程返回值)6、回收子线程的返回值pthread_detach()1、背景2、函数原型3、返回值4、detached状态 线程创建相关API函数 pthread _create(创建线程函数) 1. 头文件 #

JMW1407的博客 3013

模拟ic入门——设计一个单极运放(一)单级运算放大器设计基础

主要介绍了单级运放的基本理论和使用场景

qq_64956710的博客 3738

Linux中线程的实现,线程的接口相关函数pthread_create、pthread_join、pthread_exit

线程的基本概念,操作系统中线程的实现,linux中线程的实现,线程与进程的区别,线程的接口相关函数,代码演示

m0_62689947的博客 1500

SPSS新手教程—两步聚类之结果解读

在《详解SPSS两步聚类之参数设置》一文中,我们已经了解了两步聚类的优点、分析原理,以及参数设置的技巧。 在本节中,会对IBM SPSS Statistics聚类后的结果进行解读,其中会涉及到最终聚类的结果、聚类的质量、变量重要性、聚类特征的解读。 如图1所示,我们先来回顾下本例数据在参数设置面板中的详细设置。 图1:二阶聚类设置 一、数值结果 根据上述参数设置,得到如下的数值分析结果。 首先看到自动聚类结果,如图2所示为聚类的透视表结果,展示了不同聚类数目下的BIC、BIC变化量、BIC变

nekonekoboom的博客 3万+

有史以来最小的GIF/png/jpg/jpeg

昨天我对图像进行了 base64 编码,这样我就可以将它发送到 CouchDB 以测试我正在为客户编写的一些代码。它让我想起了我之前在远程服务器上设置 cookie 时所做的事情。基本上,一个小的 PHP 脚本被放在远程服务器上,它接受几个 GET 参数并根据它们的值设置一些 cookie。然后脚本输出一个 1x1 的透明 GIF。本地服务器上的 PHP 脚本生成了一个 IMG 标签,该标签链接到该图像并根据本地服务器上的 COOKIES 设置参数。

凌凌1301的博客 1416

【Linux教程】Linux中用C语言多线程编程之pthread_join()函数

Linux中用C语言多线程编程之pthread_join()函数 在Ubuntu Linux上用C语言进行多线程编程 一运行就报错 报错如下: 段错误 (核心已转储) 经过多次调试 发现是因为创建了多线程但没有进行多个线程之间的连接 而对多线程进行连接要用到pthread_join()函数 下面学习学习pthread_join()函数 pthread_join()函数 : 函数pthread...

菜鸟的后花园 3789

Cluster Computing期刊投稿实战:从格式调整到技术检查的全流程解析

本文详细解析了向Cluster Computing期刊投稿的全流程,涵盖心理准备、格式调整、参考文献处理及投稿系统操作。重点介绍了如何利用Springer LaTeX模板,特别是使用picins宏包解决作者简介排版难题,并强调了将BibTeX转换为BBL文件以避免技术审查陷阱,为研究者提供了一份实用的投稿指南。

weixin_28432777的博客 665

linux_线程基础函数-pthread_self函数-pthread_create函数-pthread_exit函数-pthread_join函数

在一个线程中调用pthread_create()创建新的线程后,当前线程从pthread_create()返回继续往下执行,而新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。线程id的类型是thread_t,它只在当前进程中保证是唯一的,在不同的系统中thread_t这个类型有不同的实现,它可能是一个整数值,也可能是一个结构体,也可能是一个地址,所以不能简单地当成整数用printf打印,调用pthread_self(3)可以获得当前线程的id。

qq_44177918的博客 4169

从解压到编译:手把手带你用TeXstudio搞定第一篇ACM LaTeX论文

本文详细指导如何使用TeXstudio从解压ACM LaTeX模板到成功编译第一篇学术论文的全过程。涵盖环境准备、模板配置、TeXstudio设置及常见问题排查,特别针对ACM会议论文格式要求,帮助学术新人快速掌握LaTeX写作技巧。

weixin_30655569的博客 254

Autosar Configuration(十四)SomeIP之配置SoAd

本文主要介绍SomeIp协议栈中的SoAd在Configurator中的详细配置

king110108的专栏 2600

Linux 线程2-线程ID获取、回收线程空间pthread_join、线程状态设置pthread_detach、线程退出pthread_exit、线程取消pthread_cancel、线程清理函数

Linux 线程2-线程ID获取pthread_self、回收线程空间pthread_join、线程状态设置pthread_detach、线程退出pthread_exit、线程取消pthread_cancel:pthread_setcancelstate线程的取消状态、pthread_testcancel线程的取消点、pthread_setcanceltype线程的取消类型、线程取消点分类、线程清理函数pthread_cleanup_pop

weixin_45925859的博客 1125

PCL 使用点云创建数字高程模型DEM【2025最新版】

使用点云创建数字高程模型DEM,并将结果保存为高程图像。博客长期更新,本文最近更新时间为:2025年9月15日。

点云侠的博客 2294

线程的使用学习pthread_create函数详解(向线程函数传递参数)以及linux中pthread_join()与pthread_detach()详解和#define和#ifdef的使用#if 1

1.linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)。只有当你调用了pthread_join之后这些资源才会被释放。若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放。

梁俊星的博客 1911

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: 内核同步机制-信号量
下一篇: 共享内存—内存映射mmap
ShowMan
博客等级 码龄26年 280粉丝 321原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值