900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Linux下多线程编程---02(线程退出与线程资源的回收)

Linux下多线程编程---02(线程退出与线程资源的回收)

时间:2020-08-23 05:36:16

相关推荐

Linux下多线程编程---02(线程退出与线程资源的回收)

线程退出的三种情况:第一种是进程结束,进程中所有的线程也会随之结束。第二种是通过函数 pthread_exit 来主动的退出线程。第三种被其他线程调用 pthread_cancel 来被动退出。

当线程结束后,主线程可以通过函数 pthread_join/pthread_tryjoin_np来回收线程的资源,并且获得线程结束后需要返回的数据。因为在Linux系统中程序的线程资源是有限的,表现为对于一个程序其能同时运行的线程数是有限的。而默认的条件下,一个线程结束后,其对应的资源不会被释放,于是,如果在一个程序中,反复建立线程,而线程又默认的退出,则最终线程资源耗尽,进程将不再能建立新的线程。因此,我们在使用线程的过程中,对于已经创建的资源一定要合理的回收,防止资源泄露。

1、线程主动退出(pthread_exit () 函数的使用):

#include <pthread.h>void pthread_exit(void *retval);

pthread_exit ()函数为线程退出函数,在退出时候可以传递一个 void* 类型的数据带给主线程,若选择不传出数据,可将参数填充为 NULL。

2、线程被动退出(pthread_cancel ()):

#include <pthread.h>int pthread_cancel(pthread_t thread);

该函数传入一个 tid 号,会强制退出该 tid 所指向的线程,若成功执行会返回 0。

使用以上两个函数进行线程的退出,但是相对应的资源(子线程创建时从父线程copy出来的栈内存;子线程内部单独申请的堆内存(malloc、realloc、calloc)和锁资源mutex)并不会被回收,为了防止资源的过度占用造成内存泄漏,在线程回收的时候,或者当线程处于加锁后解锁前的状态时,应当采取相应的措施来回收该线程资源。

3、线程资源回收(阻塞的方式 pthread_join ())

线程资源回收(阻塞)#include <pthread.h>int pthread_join(pthread_t thread, void **retval);

使用该函数对线程资源进行回收,默认采用阻塞的方式,直到成功回收后才会返回,第一个参数为要回收线程的 tid 号,第二个参数为线程回收后接受线程传出的数据。

4、线程资源回收( 非阻塞方式 pthread_tryjoin_np () )

线程资源回收(非阻塞)#define _GNU_SOURCE#include <pthread.h>int pthread_tryjoin_np(pthread_t thread, void **retval);

该函数为非阻塞模式回收函数,通过返回值判断是否回收掉线程,成功回

收则返回 0,其余参数与 pthread_join 一致

线程分为可结合的(joinable)和 分离的(detached)两种,如果没有在创建线程时设置线程的属性为PTHREAD_CREATE_DETACHED,则线程默认是可结合的,以上方式使用的均为可结合线程。可结合的线程在线程退出后不会立即释放资源,必须要调用pthread_join来显式的结束线程。分离的线程在线程退出时系统会自动回收资源。

3/4 .1 如何设置分离线程?

1.在创建线程时加上

pthread_attr_tattr;

pthread_tthread;

pthread_attr_init(&attr);

/*设置线程的属性为分离的*/

pthread_attr_setdetachstat(&attr,PTHREAD_CREATE_DETACHED);

pthread_create(&thread,&attr,&thread_function,NULL);

/*销毁一个目标结构,并且使它在重新初始化之前不能重新使用*/

pthread_attr_destroy(&attr);

2.在线程中调用pthread_detach(pthread_self());

3.主线程中调用pthread_detach(pid),pid为子线程的线程号

要注意的是:设置为分离的线程是不能调用pthread_join的,调用后会出错。

同时,pthread_create 创建线程时,若不指定分配堆栈大小,系统会分配默认值,查看默认值方法如下:

# ulimit -s

8192

#

上述表示为8M;单位为KB。

在嵌入式中内存不是很大,若采用默认值的话,会导致出现问题,若内存不足,则 pthread_create 会返回 12。在此就不再添加如何重新设置堆栈内容,需要使用到的时候可以去如下链接查找相关代码。其中如上部分内容也来自该博文。

链接地址:Linux线程退出、资源回收、资源清理的方法 - CTHON - 博客园 ()

例程 1:

#例程 01#include <stdio.h>#include <pthread.h>void* func1(void* arg){static int str = 0; //作为静态局部变量,将存入全局变量的内存空间,该函数结束调用后,//参数的内存空间不会被释放。str = *(int*)arg;str++;printf("func1: %d,addr:%p\n",str,&str);pthread_exit((void*)&str);}int main(){int ret;int *tmp;int a = 10;pthread_t tid1;pthread_create(&tid1,NULL,func1,(void*)&a);pthread_join(tid1,(void*)&tmp);printf("tmp get :%d,addr:%p\n",*tmp,tmp);return 0;}

例程 2:

#define _GNU_SOURCE #include <stdio.h>#include <pthread.h>#include <unistd.h>void* func(void* arg){printf("Pthread:%d Come !\n",(int)(long)arg+1);pthread_exit((void*)arg);}int main(){pthread_t array[3];int str;int ret;int i;int flag = 0; for(i = 0;i < 3;i++){ret = pthread_create(&array[i],NULL,func,(void*)(long)i);//if(ret != 0){printf("create %d thread failed\n",i);perror("Why:\n");return -1;}}while(1){for(i = 0;i < 3;i++){if(pthread_tryjoin_np(array[i],(void*)&str) == 0){printf("%d thread exit\n",(int)str + 1);flag++;}}if(flag >= 3){break;}}return 0;}

分析:循环创建3个线程,并且将其 i 的顺序作为参数传入线程程序,在主函数中采用非阻塞方式回收线程资源,并且设置 flag 标志位,当三个线程资源全部被回收的时候,主函数结束。

例程 3 :

#define _GNU_SOURCE #include <stdio.h>#include <pthread.h>#include <unistd.h>void* func1(void* arg){printf("This is pthread 1,come!\n");while(1){sleep(1);}}void* func2(void* arg){printf("This is pthread 2,come!\n");pthread_cancel((pthread_t)arg);pthread_exit((void*)pthread_self());}int main(){int ret;int i;int str;pthread_t array[2];ret = pthread_create(&array[0],NULL,func1,NULL);if(ret != 0){printf("create first pthread failed\n");perror("Why:\n");return -1;}pthread_create(&array[1],NULL,func2,(void*)array[0]);if(ret != 0){printf("create first pthread failed\n");perror("Why:\n");return -1;}int flag = 0;while(1){for(i = 0;i < 2;i++){if(pthread_tryjoin_np(array[i],(void*)&str) == 0){printf("%d exit\n",str);flag++;}}if(flag == 2) break;}return 0;}

分析:首先创建了线程1,其一创建就会处于睡眠状态,只有等到线程2创建后执行线程1强制退出后,才会结束该线程,随后主函数通过非阻塞的方式进行回收资源。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。