Pthread线程的资源的释放

线程的退出与其相关资源的释放

Pthread创建线程后必须使用join或detach释放线程资源;
首先说明一下几个函数的用法:

1.#include
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状态

#include #include #include void print_message( void *ptr ); int main( int argc, char *argv[] ) { pthread_t thread_id; int rc; int num = 5; do{ printf("In main: creating thread %d\n",num); rc = pthread_create( &thread_id, NULL, (void *)print_message, (void *)NULL );// 一个线程默认的状态是joinable if (rc != 0) { printf("ERROR; return code from pthread_create() is %d\n", rc); } } while(num--); printf("\n— main End —- \n"); return 0; } void print_message( void *ptr ) { pthread_detach(pthread_self());//pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放 static int g; printf("children thread:%d \n", g++); pthread_exit(0) ;//pthread_exit时自动会被释放 }

2. 在创建线程的设置PTHREAD_CREATE_DETACHED属性,unjoinable属性可以在pthread_create时指定

#include #include #include void* print_message( void *ptr ); int main( int argc, char *argv[] ) { pthread_t thread_id; int rc; int num = 5; do{ printf("In main: creating thread %d\n",num); pthread_attr_t attr; pthread_t thread; pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); rc = pthread_create( &thread_id, &attr, (void *)print_message, (void *)NULL );// 线程状态指定为unjoinable if (rc != 0) { printf("ERROR; return code from pthread_create() is %d\n", rc); } pthread_attr_destroy (&attr); } while(num--); printf("\n— main End —- \n"); return 0; } void* print_message( void *ptr ) { static int g_num; printf("children thread:%d \n", g_num++); pthread_exit(NULL); }

3. 默认线程状态为joinable,需要创建线程后用 pthread_join()一直等待子线程结束,释放资源。

#include #include #include void* print_message( void *ptr ); int main( int argc, char *argv[] ) { pthread_t thread_id; int rc; int num = 5; void *thread_return; do{ printf("In main: creating thread %d\n",num); rc = pthread_create( &thread_id, NULL, (void *)print_message, (void *)NULL );// 一个线程默认的状态是joinable if (rc != 0) { printf("ERROR; return code from pthread_create() is %d\n", rc); } /*等待线程thread_id结束*/ pthread_join(thread_id, &thread_return); //这里的thread_id是被等待线程的ID,这里一直阻塞一直到被等待的线程结束为止 printf("%d\n", (int)thread_return); } while(num--); printf("\n— main End —- \n"); return 0; } void* print_message( void *ptr ) { static int g_num; printf("children thread:%d \n", g_num++); //用pthread_exit()来调用线程的返回值,用来主动退出线程,但是退出线程所占用的资源不会随着线程的终止而得到释放, //而是到pthread_join调用后才释放资源。 pthread_exit((void *)g_num); //或者用return((void *)g_num); //return((void *)g_num); }

你可能感兴趣的:(C语言,linux系统编程)