为什么需要线程等待?
1.线程的入口函数是有返回值的,有时候需要查看这个结果;
2.这个结果会在线程退出时一直在内存中保存着,直到有其他线程来读取,才会释放;
3.否则,会产生类似于僵尸进程的场景,创建新的线程不会复用刚才退出线程的地址空间。
4.如果没有pthread_join(),主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了,加入pthread_join()后,主线程会一直等待,直到等待的线程结束自己,才会结束这个整个进程,也就是说pthread_join可以使创建的线程有机会执行
pthread_join
功能:等待线程结束(此函数使一个线程等待另一个线程结束)
原型:
int pthread_join(pthread_t thread,void**value_ptr)
参数说明:
thread:线程ID
value_ptr:它指向一个指针,后者指向线程的返回值
ps:参数value_ptr 是输出型参数,需要输出的内容是void*,所以在这里
是void**来接收参数
调用该函数的线程将会挂起等待,直到ID为thread的线程终止
此等待是阻塞式等待,就是会等待的线程什么也不做,一直等待某线程结束,才会去做自己该做的事
thread线程以不同的方法终止,那通过pthread_join得到的终止状态是不同的,如下:
1.如果ID为thread的线程通过return返回,value_ptr
所指向的单元里存放的是thread线程函数的返回值
2.如果ID为thread的线程是被别的线程调用pthread_cancel
异常终止,value_ptr所指向的单元里存放的是常数PTHREAD_CANCELED
3.如果ID为thread的线程是自己调用pthread_exit终止的,value_ptr
所指向的单元里存放的是传给pthread_exit的参数
4.如果对ID为thread的线程的终止状态不感兴趣,可以传NULL给value_ptr参数
示例
1.
代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
typedef struct Student
{
int id;
int score;
char *name;
}Student;
void*ThreadEntry(void*arg)
{
(void)arg;
int count=0;
Student*p=(Student*)malloc(sizeof(Student));
p->id=29;
p->score=100;
p->name="xiaoming";
while(1)
{
++count;
if(count>=5)
return (void*)p;
printf("I am thread\n");
sleep(1);
}
}
int main()
{
pthread_t tid;
void*ret;
int thread=0;
thread=pthread_create(&tid,NULL,ThreadEntry,NULL);
if(thread!=0)
{
perror("pthread_create");
exit(1);
}
printf("I am main\n");
pthread_join(tid,&ret);
Student*st=(Student*)ret;
printf("id=%d,score= %d ,name=%s\n",st->id,st->score,st->name);
return 0;
}
运行结果:
2.
代码:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void*ThreadEntry(void*arg)
{
int count=0;
int*p=(int*)malloc(sizeof(int));
*p=50;
while(1)
{
++count;
if(count>5)
pthread_exit(p);
printf("I am thread\n");
sleep(1);
}
}
int main()
{
pthread_t tid;
void*ret;
int thread;
thread=pthread_create(&tid,NULL,ThreadEntry,NULL);
if(thread!=0)
{
perror("pthread_create");
exit(1);
}
printf("I am main\n");
pthread_join(tid,&ret);
printf("ret=%d\n",*(int*)ret);
return 0;
}
运行结果:
ps:void*是怎么构造的,那就一定要按相同的类型去解析
3.
代码:
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
void*thread1(void*arg)
{
printf("thread1 is return..............\n");
int*p=(int*)malloc(sizeof(int));
*p=20;
return (void*)p;
}
void*thread2(void*arg)
{
printf("thread2 is pthread_exit!\n");
int*p=(int*)malloc(sizeof(int));
*p=50;
pthread_exit(p);
}
void*thread3(void*arg)
{
while(1)
{
printf("thread3 is pthread_cancel.............\n");
sleep(1);
}
}
int main()
{
pthread_t tid;
void*ret;
//thread1
pthread_create(&tid,NULL,thread1,NULL);
pthread_join(tid,&ret);
printf("thread1 return,thread is %1x,return code:%d\n",tid,*(int*)ret);
free(ret);//malloc开辟内存后记得释放开辟的空间
sleep(1);
printf("\n");
//thread2
pthread_create(&tid,NULL,thread2,NULL);
pthread_join(tid,&ret);
printf("thread2 pthread_exit,thread is %1x,return code:%d\n",tid,*(int*)ret);
free(ret);//malloc开辟内存后记得释放开辟的空间
sleep(1);
printf("\n");
//thread3
pthread_create(&tid,NULL,thread3,NULL);
sleep(3);
pthread_cancel(tid);
pthread_join(tid,&ret);
if(ret==PTHREAD_CANCELED)
printf("thread3 pthread_cancel,thread is %1x,return code:PTHREAD_CANCELED\n",tid);
return 0;
}
运行结果: