1 pthread_exit函数
void pthread_exit(void *retval);
/*
功能:退出当前子线程。与在某个函数中返回区别一下。
参1:retval表示线程退出状态,通常传NULL。
*/
2 exit的作用
1)测试1
下面的程序和结果可以看到,当执行到第二个线程时,我们调用了exit(0),导致后面3,4,5线程没有打印。也就是说,该函数会将整个进程退出,无论在哪个线程中。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int func(int a){
exit(0);
}
void *tfn(void *arg){
int i;
i = (int)arg;
sleep(i);
if (i == 2){
func(8888);//测试1
//return NULL;//测试2
//func(8888);//测试3
}
printf("I'm %dth thread, Thread_ID = %lu\n", i+1, pthread_self());
pthread_exit(NULL);
}
int main(int argc, char *argv[]){
int n = 5, i;
pthread_t tid[n];
for (i = 0; i < n; i++) {
tid[i] = -1;
}
for (i = 0; i < n; i++) {
pthread_create(&tid[i], NULL, tfn, (void *)i);
}
//为了方便观察,不回收
//for (i = 0; i < n; i++) {
//pthread_join(tid, NULL);
//}
printf("I am main, and I am not a process, I'm a thread!\n"
"main_thread_ID = %lu\n", pthread_self());
return 0;
}
程序结果:
3 return的作用
1)测试2
同样的代码,我们将func函数中的exit改成return NULL,可以看到结果1能够依次打印。
结果1:
2)测试3
然后再将return NULL封装一下放在一个新的函数func中返回,重新调用func,可以看到结果2,我们想要退出线程3,但却没有退出。
void* func(){
return NULL;
}
结果2:
- 所以可以总结到return的作用是:返回到调用者处。有可能会退出进程(放在主线程时),有可能会退出线程,也有可能什么也不退出。
3 pthread_exit的作用
将测试3的代码改成下面,可以看到结果,线程3退出了。所以pthread_exit的作用是只退出当前子线程,记住是只。即使你放在主线程,它也会只退出主线程,其它线程有运行的仍会继续运行。
void* func(){
pthread_exit(NULL);
}
结果:
所以我们可以大总结这些退出函数的作用了。
4 总结exit、return、pthread_exit,pthread_cancel各自退出效果和pthread_join,pthread_detach的作用
- 1)return:返回到调用者那里去。注意,在主线程退出时效果与exit,_exit一样。即return有可能会退出进程(放在主线程时),有可能会退出线程,也有可能什么也不退出。
- 2)pthread_exit():只退出当前子线程。注意:在主线程退出时,其它线程不会结束。同样可以执行。所以这个只字非常重要。并且,与return一样,pthread_exit退出的线程也需要调用pthread_join去回收子线程的资源(8k左右),否则服务器长时间运行会浪费资源导致无法再创建新线程。
- 3)exit,_exit: 将进程退出,无论哪个子线程调用整个程序都将结束。
- 4)pthread_join():阻塞等待回收子线程。
- 5)pthread_cancel():可以杀死子线程,但必须需要一个契机,这个契机就是系统调用。一般方法是调用pthread_testcancel提供契机处理。并且join再回收该被杀死的子线程的返回值为pthread.h中的宏#define PTHREAD_CANCELED ((void *) -1)。
- 6)pthread_detach:1)注意,所有线程的错误号返回都只能使用strerror这个函数判断,不能使用perror,因为perror是调用进程的全局错误号,不适合单独线程的错误分析,所以只能使用strerror。2)线程可以被置为detach状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join,这样的调用将返回EINVAL错误。也就是说,如果已经对一个线程调用了pthread_detach就不能再调用pthread_join了。