在线程中禁止调用exit函数,否则会导致整个进程退出,取而代之的是调用pthread_exit函数,这个函数是使一个线程退出,如果主线程调用pthread_exit函数也不会使整个进程退出,不影响其他线程的执行。
- 函数描述:将单个线程退出
- 函数原型:void pthread_exit(void *retval);
- 函数参数:retval表示线程退出状态,通常传NULL
需要注意一点,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了,栈空间就会被回收。
如果在主线程中使用pthread_exit函数,会导致子线程还在,内存无法被回收,成为僵尸进程。引入pthread_join函数。
pthread_join函数
- 函数描述:阻塞等待线程退出,获取线程退出状态。其作用,对应进程中的waitpid() 函数。
- 函数原型:int pthread_join(pthread_t thread, void **retval);
- 函数返回值:成功:0;失败:错误号
- 函数参数:
- thread:线程ID
- retval:存储线程结束状态,整个指针和pthread_exit的参数是同一块内存地址。
引入一个例子使主线程获取子线程的退出状态:
代码如下:
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
struct Test
{
int data;
char name[64];
};
int g_var = 9;
struct Test t;
//线程执行函数
void *mythread(void *arg)
{
printf("child thread, pid==[%d], id==[%ld]\n", getpid(), pthread_self());
//printf("[%p]\n", &g_var);
//void pthread_exit(void *retval);
//pthread_exit(&g_var);
memset(&t, 0x00, sizeof(t));
t.data = 99;
strcpy(t.name, "xiaowen");
pthread_exit(&t);
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
// void *(*start_routine) (void *), void *arg);
//创建子线程
pthread_t thread;
int ret = pthread_create(&thread, NULL, mythread, NULL);
if(ret!=0)
{
printf("pthread_create error, [%s]\n", strerror(ret));
return -1;
}
printf("main thread, pid==[%d], id==[%ld]\n", getpid(), pthread_self());
//回收子线程
void *p = NULL;
// int pthread_join(pthread_t thread, void **retval);
pthread_join(thread, &p); //&p中存放&g_var的地址
//int n = *(int *)p;
struct Test *pt = (struct Test *)p;
printf("child exit status:[%d],[%s],[%p]\n", pt->data, pt->name, p);
return 0;
}
~
结果如下:主线程获取了子线程的退出状态:即结构体中的内容。