`

linux pthread detach 和 joinable属性

阅读更多

这两天在看Pthread 资料的时候,无意中看到这样一句话(man pthread_detach):

Either pthread_join(3) or pthread_detach() should be called for each thread
       that an application creates, so that system resources for the thread can be
       released.  (But note that the resources of all threads are freed when the
       process terminates.)

也就是说:每个进程创建以后都应该调用pthread_join 或 pthread_detach 函数,只有这样在线程结束的时候资源(线程的描述信息和stack)才能被释放.

之后又查了pthread_join 但是没有明确说明必须调用pthread_join 或 pthread_detach.

但是再查了 Pthread for win32 pthread_join

When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore, pthread_join must be called  once  for each joinable thread created to avoid memory leaks.

 
才知道如果在新线程里面没有调用pthread_join 或 pthread_detach会导致内存泄漏, 如果你创建的线程越多,你的内存利用率就会越高, 直到你再无法创建线程,最终只能结束进程。
 
解决方法有三个:
1.   线程里面调用 pthread_detach(pthread_self()) 这个方法最简单
2. 在创建线程的设置PTHREAD_CREATE_DETACHED属性
3. 创建线程后用 pthread_join() 一直等待子线程结束。
 
下面是几个简单的例子
1. 调用  pthread_detach(pthread_self())
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *PrintHello(void)
{
pthread_detach(pthread_self());
int stack[1024 * 20] = {0,};
//sleep(1);
long tid = 0;
//printf(“Hello World! It’s me, thread #%ld!\n”, tid);
//pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t pid;
int rc;
long t;
while (1) {
printf(“In main: creating thread %ld\n”, t);
rc = pthread_create(&pid, NULL, PrintHello, NULL);
if (rc){
printf(“ERROR; return code from pthread_create() is %d\n”, rc);
//exit(-1);
}
sleep(1);
}
printf(” \n— main End —- \n”);
pthread_exit(NULL);
}
2. 在创建线程的设置PTHREAD_CREATE_DETACHED属性
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *PrintHello(void)
{
int stack[1024 * 20] = {0,};
//pthread_exit(NULL);
//pthread_detach(pthread_self());
}
int main (int argc, char *argv[])
{
pthread_t pid;
int rc;
long t;
while (1) {
printf(“In main: creating thread %ld\n”, t);
pthread_attr_t attr;
pthread_t thread;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
rc = pthread_create(&pid, &attr, PrintHello, NULL);
pthread_attr_destroy (&attr);
if (rc){
printf(“ERROR; return code from pthread_create() is %d\n”, rc);
//exit(-1);
}
sleep(1);
}
printf(” \n— main End —- \n”);
pthread_exit(NULL);
}
3. 创建线程后用 pthread_join() 一直等待子线程结束。
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *PrintHello(void)
{
int stack[1024 * 20] = {0,};
//sleep(1);
long tid = 0;
//pthread_exit(NULL);
//pthread_detach(pthread_self());
}
int main (int argc, char *argv[])
{
pthread_t pid;
int rc;
long t;
while (1) {
printf(“In main: creating thread %ld\n”, t);
rc = pthread_create(&pid, NULL, PrintHello, NULL);
if (rc){
printf(“ERROR; return code from pthread_create() is %d\n”, rc);
//exit(-1);
}
pthread_join(pid, NULL);
sleep(1);
}
printf(” \n— main End —- \n”);
pthread_exit(NULL);
}
 

最近解决了一个隐蔽的内存泄漏问题,我们的进程是HA模式,用户不停的切换,会导致内存不停的增长,切换一次,再切回来内存便增加8M左右。原因就是是pthread_create后的僵死线程没有释放导致的内存持续增长。

 

pthread_create (&thread, NULL, &thread_function, NULL); 就这么写了,参数2没有设置线程结束后自动detach,并且没有使用pthread_join或pthread_detach释放执行结束后线程的空间!

 

Linux man page 里有已经说明了这个问题:
    When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore, pthread_join must be called  once  for each joinable thread created to avoid memory leaks.

也就说线程执行完后如果不join的话,线程的资源会一直得不到释放而导致内存泄漏!

 

解决办法

 

创建线程前设置 PTHREAD_CREATE_DETACHED 属性
 pthread_attr_t attr;
 pthread_t thread;
 thread_attr_init (&attr);
 pthread_attr_setdetachstate (&attrPTHREAD_CREATE_DETACHED);
 pthread_create (&thread, &attr&thread_function, NULL);
 pthread_attr_destroy (&attr);

这样就会在线程return/pthread_exit后释放内存。

其实用valgrind检查时会提示pthread_create没有释放的问题,这样的问题也只有在长时间运行时,慢慢积累这一点点的内存才会暴露出来。

 

 

属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数 之前调用。属性对象主要包括是否绑定、是否分离、堆栈地址、堆栈大小、优先级。默认的属性为非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。

线程的分离状态决定一个线程以什么样的方式来终止自己。在上面的例子中,我们采用了线程的默认属性,即为非分离状态,这种情况下,原有的线程等待 创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其 他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。设置线程分离状态的函数为pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。第二个参数可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD _CREATE_JOINABLE(非分离线程)。

分享到:
评论

相关推荐

    pthread手册.doc

    - `PTHREAD_CREATE_JOINABLE`:非分离状态,线程结束时需要通过`pthread_join`等待其结束。 - **返回值**:成功返回0,否则返回错误码。 #### 四、注意事项 - 在使用`pthread_create`创建线程时,建议先初始化...

    pthread经典用法

    在这个例子中,`pthread_create()`函数用于创建新的线程,参数分别为线程ID指针、线程属性(默认为NULL)、线程入口函数和传递给该函数的参数。主线程会打印"I am main thread",而新创建的线程则循环打印"hello ...

    linux多线程设计及示例

    本文将深入探讨Linux环境下多线程的设计、创建、管理和相关属性。 1. **线程创建** 使用`pthread_create`函数可以创建一个新的线程。这个函数需要四个参数:线程标识符的指针,线程属性(默认为NULL,表示使用默认...

    日常记录学习,基础知识,学习笔记

    在编写多线程程序时,合理地使用`pthread_self()`、`pthread_join()`和`pthread_detach()`,以及妥善处理端口冲突,可以有效地优化程序性能并避免资源浪费。同时,熟悉这些基本工具和概念,也有助于排查和解决实际...

    多线程学习笔记,关于创建线程,删除线程等相关指令的应用。

    以下是一些关于多线程的重要知识点,特别是关于在Linux和Windows环境下创建和管理线程的关键指令。 1. **线程状态**: - **Joinable状态**:这是大多数线程的默认状态。在这种状态下,当线程完成执行后,其资源...

    Posix线程编程指南

    此外,线程属性可以通过`pthread_attr_init()`、`pthread_attr_destroy()`以及一系列的`pthread_attr_get*`和`pthread_attr_set*`函数进行初始化和修改。 Posix线程编程不仅涉及到线程的创建和管理,还包括线程同步...

    分离状态创建线程

    若不关心线程的结束状态,可以使用`pthread_detach()`函数将线程设置为分离状态,或者在创建线程时通过设置线程属性`detachstate`为`PTHREAD_CREATE_DETACHED`使其从一开始就成为分离线程。 总结来说,线程的分离...

    Posix线程编程 适合初学者

    如`pthread_join()`用来等待线程结束,`pthread_cancel()`用于取消线程,`pthread_exit()`让线程正常或异常退出,以及`pthread_attr_init()`和`pthread_attr_destroy()`用于初始化和销毁线程属性对象。 Posix线程...

    Linux下线程简单使用

    在某些Linux系统中,可以通过`pthread_setschedparam`函数设置线程优先级,但这并不总是有效,因为线程调度策略取决于具体内核配置。 六、线程安全的STL容器 C++11引入了线程安全的容器,如`std::atomic`,它可以...

    Linux多线程编程快速入门

    - **非joinable线程(detached)**:通过设置线程属性为detach状态,线程完成后资源会被自动回收,无需主线程join。 5. **示例代码** - 上述代码创建了一个新的线程`thread_func`,在主线程中调用`pthread_create...

    详解C++ thread用法总结

    例如,在Linux系统中,native_handle_type实际上对应于pthread_t类型,允许程序员通过std::thread实例调用pthread库的函数。swap函数允许交换两个线程对象的底层句柄,而硬件并发数可以通过hardware_concurrency静态...

Global site tag (gtag.js) - Google Analytics