Pthread创建线程后必须使用join或detach释放线程资源;
首先说明一下几个函数的用法:
1.#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,
const pthread_attr_t *restrict attr,
void *(*start_rtn)(void),
void *restrict arg);
Returns: 0 if OK, error number on failure
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。
2.pthread_self():函数用来获取当前调用该函数的线程的线程ID;
3.pthread_join():用来等待一个线程的结束。函数原型为:
extern int pthread_join __P ((pthread_t __th, void **__thread_return));
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。
这个函数是一个线程阻塞的函数,调用它的线程将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们 上面的例子一样,函数结束了,调用它的线程也就结束了;另外一种就是调用函数pthread_exit。
①join是三种同步线程的方式之一。另外两种分别是互斥锁(mutex)和条件变量(condition variable)。
②调用pthread_join()将阻塞自己,一直到要等待加入的线程运行结束。
③可以用pthread_join()获取线程的返回值。
④一个线程对应一个pthread_join()调用,对同一个线程进行多次pthread_join()调用是逻辑错误。
4.pthread_exit():它的函数原型为:
extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
唯一的参数是函数的返回代码,只要pthread_exit中的参数retval不是NULL,这个值将被传递给thread_return。
使用函数pthread_exit退出线程,这是线程的主动行为;
★最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。
★linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态。
一个线程默认的状态是joinable,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符
(总计8K多)。只有当你调用了pthread_join之后这些资源才会被释放。
若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放。unjoinable属性可以在pthread_create时指定,或在线程创建后在线程中 pthread_detach自己, 如:pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放。
如果线程状态为joinable,需要在之后适时调用pthread_join。
所以如果在新线程里面没有调用pthread_join 或 pthread_detach会导致内存泄漏, 如果你创建的线程越多,你的内存利用率就会越高, 直到你再无法创建线程,最终只能结束进程。
解决方法有三个:
1. 调用pthread_detach(pthread_self()),将状态改为unjoinable状态
2. 在创建线程的设置PTHREAD_CREATE_DETACHED属性,unjoinable属性可以在pthread_create时指定
3. 默认线程状态为joinable,需要创建线程后用 pthread_join()一直等待子线程结束,释放资源。

本文详细介绍了Pthread线程的资源释放,包括pthread_create、pthread_self、pthread_join和pthread_exit的用法。重点讨论了如何避免线程资源泄露,提出了通过pthread_detach和设置PTHREAD_CREATE_DETACHED属性以及使用pthread_join来释放资源的解决方案。
1084

被折叠的 条评论
为什么被折叠?



