一、线程的两种状态
对于 linux 线程来说,pthread 有两种状态:joinable 和 unjoinable。
若线程的状态是 joinable,当线程函数自己返回退出时或 pthread_exit() 时都不会释放线程所占用堆栈和线程描述符(总计 8K 多),只有当你调用了 pthread_join() 之后这些资源才会被释放。
若线程的状态是 unjoinable,这些资源在线程函数退出时或 pthread_exit() 时自动会被释放。
二、unjoinable 设置方法
unjoinable 属性可以在 pthread_create() 时指定,或在线程创建后在线程中 pthread_detach() 自己, 如:pthread_detach(pthread_self()),将状态改为 unjoinable 状态,确保资源的释放。
其实简单的说就是在线程函数头加上 pthread_detach(pthread_self()) 的话,线程状态改变,在函数尾部直接 pthread_exit() 线程就会自动退出,省去了给线程擦屁股的麻烦。
#if 0
pthread_attr_t attr; /*通过线程属性来设置游离态(分离态)*/
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, tfn, NULL);
#else
pthread_create(&tid, NULL, tfn, NULL);
pthread_detach(tid); //让线程分离 ----自动退出,无系统残留资源
#endif
三、pthread_join 和 pthread_detach 区别
- pthread_join() ,即:以阻塞的方式等待指定的线程结束。当函数返回时,被等待线程的资源被收回;如果线程已经结束,那么该函数会立即返回。上述的前提是线程必须是 joinable 的。可以这么理解,pthread_join() 函数的作用就是在main() 函数退出之前等待子线程退出,从而可以达到回收子线程剩余内存的目的。
- pthread_detach(),即:主线程与子线程分离,子线程结束后,资源自动回收。
四、注意
使用 pthread_detach 函数实现线程分离时,应当先创建线程(pthread_create),然后再用pthread_detach 实现该线程的分离。因为,这种方式与修改线程属性来实现线程分离的方法相比,不会发生在线程创建函数还未来得及返回时子线程提前结束导致返回的线程号是错误的线程号的情况。
采用这种方法,即使子线程提前结束(先于 pthread_create 返回),但是子线程还未处于分离状态,因此其 PCB 的残留信息依然存在,如线程号等一些系统资源,所以线程号等系统资源仍被占据,还未分配出去,所以创建函数返回的线程号依然是该线程的线程号。
(SAW:Game Over!)