当主线程先于其它进程执行 pthread_exit() 时,进程还不会退出,只有最后一个线程也完成了,进程才会退出。执行exit()或者在主线程执行return,会立即终止进程的执行。
一个可“join”的线程所占用的内存仅当有线程对其执行立pthread_join()后才会释放,因此为了避免内存泄漏,所有线程的终止时,要么已被设为DETACHED,要么使用pthread_join()来回收资源。
一个线程不能被多个线程等待,否则第一个接受到信号的线程成功返回,其余调用pthread_join()的线程返回错误代码ESRCH
void pthread_exit(void* retval); int pthread_join(pthread_t thread, void **retval);
pthread_join()函数将调用线程挂起,直到参数thread指定的目标线程终止运行为止。pthread_join()参数 retval 的作用是为指向线程的返回值的指针提供一个位置, 这个返回值是目标线程调用 pthread_exit()或者 return 后所返回的值。当目标线程无需返回时可使用 NULL 值,调用线程如果不需对目标线程的返回状态进行检查可直接将 retval 赋值为 NULL。
线程状态
可以分为分离线程(DETACHED)和非分离线程(JOINABLE)两种:
分离线程是退出时会释放它的资源的线程;
非分离线程退出后不会立即释放资源,需要另一个线程为它调用 pthread_join 函数或者进程退出时才会释放资源。
在默认情况下线程是非分离状态的,这种情况下,原有的线程等待创建的线程结束。只有当pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。所以如果我们在创建线程时就知道不需要了解线程的终止状态,则可以pthread_attr_t结构中的detachstate线程属性,让线程以分离状态启动。
设置线程分离状态的函数为pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。第二个参数可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD _CREATE_JOINABLE(非分离线程)。这里要注意的一点是,如果设置一个线程为分离线程,而这个线程运行又非常快,它很可能在pthread_create函数返回之前就终止了,它终止以后就可能将线程号和系统资源移交给其他的线程使用,这样调用pthread_create的线程就得到了错误的线程号。要避免这种情况可以采取一定的同步措施,最简单的方法之一是可以在被创建的线程里调用pthread_cond_timewait函数,让这个线程等待一会儿,留出足够的时间让函数pthread_create返回。设置一段等待时间,是在多线程编程里常用的方法。但是注意不要使用诸如wait()之类的函数,它们是使整个进程睡眠,并不能解决线程同步的问题。
pthread_detach()函数可以将非分离线程设置为分离线程
线程栈
每个线程都有一个独立的调用栈,线程的栈大小在线程创建的时候就已经固定下来,Linux 系统线程的默认栈大小为 8MB,只有主线程的栈大小会在运行过程中自动增长。用户可以通过属性对象来设置和获取栈大小。
线程相关函数:
int pthread_detach(pthread_t thread);
pthread_t pthread_self(void);
int pthread_equal(pthread_t t1, pthread_t t2);
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);