//从别处拷贝过来的,只做为本身查看方便,原做者不详,请谅解。 一:关于join join join是三种同步线程的方式之一。另外两种分别是互斥锁(mutex)和条件变量(condition variable)。 调用pthread_join()将阻塞本身,一直到要等待加入的线程运行结束。 能够用pthread_join()获取线程的返回值。 一个线程对应一个pthread_join()调用,对同一个线程进行屡次pthread_join()调用是逻辑错误。 join or detach 线程分两种:一种能够join,另外一种不能够。该属性在建立线程的时候指定。 joinable线程可在建立后,用pthread_detach()显式地分离。但分离后不能够再合并。该操做不可逆。 为了确保移植性,在建立线程时,最好显式指定其join或detach属性。彷佛不是全部POSIX实现都是用joinable做默认。 二: pthread_detach 建立一个线程默认的状态是joinable, 若是一个线程结束运行但没有被join,则它的状态相似于进程中的Zombie Process,即还有一部分资源没有被回收(退出状态码),因此建立线程者应该调用pthread_join来等待线程运行结束,并可获得线程的退出代码,回收其资源(相似于wait,waitpid) 可是调用pthread_join(pthread_id)后,若是该线程没有运行结束,调用者会被阻塞,在有些状况下咱们并不但愿如此,好比在Web服务器中当主线程为每一个新来的连接建立一个子线程进行处理的时候,主线程并不但愿由于调用pthread_join而阻塞(由于还要继续处理以后到来的连接),这时能够在子线程中加入代码 pthread_detach(pthread_self()) 或者父线程调用 pthread_detach(thread_id)(非阻塞,可当即返回) 这将该子线程的状态设置为detached,则该线程运行结束后会自动释放全部资源。 三:pthread_join 调用pthread_join的线程会阻塞,直到指定的线程返回,调用了pthread_exit,或者被取消。 若是线程简单的返回,那么rval_ptr被设置成线程的返回值,参见范例1;若是调用了pthread_exit,则可将一个无类型指针返回,在pthread_join中对其进行访问,参见范例2;若是线程被取消,rval_ptr被设置成PTHREAD_CANCELED。 若是咱们不关心线程的返回值,那么咱们能够把rval_ptr设置为NULL。 范例1: #include <pthread.h> #include <string.h> void *thr_fn1(void *arg) { printf(“thread 1 returning.\n”); return((void *)1); } void *thr_fn2(void *arg) { printf(“thread 2 exiting.\n”); return((void *)2); } int main() { pthread_t tid1,tid2; void *tret; pthread_create(&tid1,NULL,thr_fn1,NULL); pthread_create(&tid2,NULL,thr_fn2,NULL); pthread_join(tid1,&tret); printf(“thread 1 exit code %d\n”,(int)tret); pthread_join(tid2,&tret); printf(“thread 2 exit code %d\n”,(int)tret); exit(0); } 运行结果: thread 1 returning. thread 1 exit code 1. thread 2 exiting. thread 2 exit code 2. 范例2: #include <stdio.h> #include <pthread.h> void thread1(char s[]) { printf("This is a pthread1.\n"); printf("%s\n",s); pthread_exit("Hello first!"); //结束线程,返回一个值。 } void thread2(char s[]) { printf("This is a pthread2.\n"); printf("%s\n",s); pthread_exit("Hello second!"); } int main(void) { pthread_t id1,id2; void *a1,*a2; int i,ret1,ret2; char s1[]="This is first thread!"; char s2[]="This is second thread!"; ret1=pthread_create(&id1,NULL,(void *) thread1,s1); ret2=pthread_create(&id2,NULL,(void *) thread2,s2); if(ret1!=0){ printf ("Create pthread1 error!\n"); exit (1); } pthread_join(id1,&a1); printf("%s\n",(char*)a1); if(ret2!=0){ printf ("Create pthread2 error!\n"); exit (1); } printf("This is the main process.\n"); pthread_join(id2,&a2); printf("%s\n",(char*)a2); return (0); } 运行结果: [****@XD**** c]$ ./example This is a pthread1. This is first thread! Hello first! This is the main process. This is a pthread2. <参考资料语> 通常状况下,进程中各个线程的运行都是相互独立的,线程的终止并不会通知,也不会影响其余线程,终止的线程所占用的资源也并不会随着线程的终止而获得释 放。正如进程之间能够用wait()系统调用来同步终止并释放资源同样,线程之间也有相似机制,那就是pthread_join()函数 pthread_join()的调用者将挂起并等待th线程终止,retval是pthread_exit()调用者线程(线程ID为th)的返回值,如 果thread_return不为NULL,则*thread_return=retval。须要注意的是一个线程仅容许惟一的一个线程使用 pthread_join()等待它的终止,而且被等待的线程应该处于可join状态,即非DETACHED状态 若是进程中的某个线程执行了pthread_detach(th),则th线程将处于DETACHED状态,这使得th线程在结束运行时自行释放所占用的 内存资源,同时也没法由pthread_join()同步,pthread_detach()执行以后,对th请求pthread_join()将返回错误 一个可join的线程所占用的内存仅当有线程对其执行了pthread_join()后才会释放,所以为了不内存泄漏,全部线程的终止,要么已设为DETACHED,要么就须要使用pthread_join()来回收 3) 主线程用pthread_exit仍是return 用pthread_exit只会使主线程自身退出,产生的子线程继续执行;用return则全部线程退出。 综合以上要想让子线程总能完整执行(不会中途退出),一种方法是在主线程中调用pthread_join对其等待,即pthread_create/pthread_join/pthread_exit或return;一种方法是在主线程退出时使用pthread_exit,这样子线程能继续执行,即pthread_create/pthread_detach/pthread_exit;还有一种是pthread_create/pthread_detach/return,这时就要保证主线程不能退出,至少是子线程完成前不能退出。如今的项目中用的就是第三种方法,主线程是一个死循环,子线程有的是死循环有的不是。 <参考资料语> 理论上说,pthread_exit()和线程宿体函数退出的功能是相同的,函数结束时会在内部自动调用pthread_exit()来清理线程相关的资源。但实际上两者因为编译器的处理有很大的不一样。 在进程主函数(main())中调用pthread_exit(),只会使主函数所在的线程(能够说是进程的主线程)退出;而若是是return,编译器将使其调用进程退出的代码(如_exit()),从而致使进程及其全部线程结束运行。