线程等待
为什么需要线程的等待?
- 已经退出的线程,其空间没有被释放,仍然在进程的地址空间。
- 创建新的线程不会复用刚才退出线程的地址空间。
调用该函数的线程将挂起状态,直到id为thread的线程终止,thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:
1、 如果thread线程通过return返回,value_ptr所指向的单元里存放的是thread线程函数的返回值。
2、如果thread线程被别的线程调用pthread_cancel异常终掉,value_ptr所指向的单元里存放的是常数PTHREAD_CANCELED(为-1是void*类型的)。
3、如果thread线程是自己调用pthreadexit终止的,valueptr所指向的单元存放的是传给ptrread_exit的参数。
4、如果对thread线程的终止状态不感兴趣,可以传给NULL给value_ptr参数。
我们来看一个线程等待的例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
void *thread1(void *arg)
{
printf("thread 1 returning ...\n");
int *p=(int*)malloc(sizeof(int));
*p=1;
return (void*)p;
}
void *thread2(void *arg)
{
printf("thread 2 exiting ...\n");
int *p=(int*)malloc(sizeof(int));
*p=2;
pthread_exit((void*)p);
}
void *thread3(void *arg)
{
while(1){
printf("thread 3 is running ...\n");
sleep(1);
}
return NULL;
}
int main()
{
pthread_t tid;
void *ret;
//thread 1 return
pthread_create(&tid,NULL,thread1,NULL);
pthread_join(tid,&ret);
printf("thread return,thread id %x,return code:%d\n",tid,*(int*)ret);
free(ret);
//thread 2 exit
pthread_create(&tid,NULL,thread2,NULL);
pthread_join(tid,&ret);
printf("thread return ,thread id %x,return code:%d\n",tid,*(int*)ret);
free(ret);
//thread 3 cancel by other
pthread_create(&tid,NULL,thread3,NULL);
sleep(3);
pthread_cancel(tid);
pthread_join(tid,&ret);
if(ret==PTHREAD_CANCELED)
{
printf("thread return,thread id %x,return code:PTHREAD_CANCELED\n",tid);
}
else
printf("thread return,thread id %x,return code:NULL\n",tid);
}
运行结果如下所示:
分离线程
默认情况线程是可结合的,代表的含义就是这个线程必须被等待。
- 默认情况下新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成系统柜的内存泄漏的问题。
- 如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。
这个函数的作用是可以是线程组内其他线程对目标线程进行分离,也可以是线程自己进行分离。
joinable和分离是冲突的,一个线程不可能既是joinable也是分离的。
线程的分离状态决定了一个线程以什么样的方式来终止自己。在默认的情况下线程是非分离状态的,这种情况下,原有的线程等待创建的线程结束。只有当 pthread_join ()函数返回时,创建的线程才算终止,才能释放自己占有用的系统资源,而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态,所以如果我们在创建线程时就知道不需要了解线程的终止状态,则可以 pthread_attr_t结构中,的detachstate线程属性,让线程以分离状态启动。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void *thread_run(void *arg)
{
pthread_detach(pthread_self());
printf("%s\n",(char*)arg);
return NULL;
}
int main()
{
pthread_t tid;
if(pthread_create(&tid,NULL,thread_run,"thread1 run ...")!=0){
printf("create thread error\n");
return 1;
}
int ret=0;
sleep(1);
if(pthread_join(tid,NULL)==0){
printf("pthread wait success\n");
ret=0;
}
else{
printf("pthread wait failed\n");
ret=1;
}
return ret;
}
结果如下:在子线程运行完毕后,分离tid后,查看是否能够等待成功,若不能则说明分离成功。