在咱们使用默认属性建立一个线程的时候,线程是 joinable 的。 joinable 状态的线程,必须在另外一个线程中使用 pthread_join() 等待其结束, 若是一个 joinable 的线程在结束后,没有使用 pthread_join() 进行操做, 这个线程就会变成"僵尸线程"。每一个僵尸线程都会消耗一些系统资源, 当有太多的僵尸线程的时候,可能会致使建立线程失败。linux
下面是一个建立僵尸线程的例子:多线程
void* start_thread(void * arg) { //这个线程什么也不作,直接退出 pthread_exit(NULL); return NULL; } int create_pthread(int n) { int try = 0; int i = 0; int err = 0; for(i = 0; i < n && try < 3; i++) { //当建立线程失败的时候,尝试3次 pthread_t pt; err = pthread_create(&pt, NULL, start_thread, NULL); if(0 != err) { if(EAGAIN == err) { printf("errno : [EAGAIN]\n"); } sleep(2); try ++; } } printf("create [%d] threads\n", i); return err; } int main(int argc, char * argv[]) { int n = 1 << 20;//最多建立 1M 个线程 create_pthread(n); return 0; }
上面代码是建立僵尸线程的主要部分,把上面代码编译执行后, 输出的结果是什么呢:spa
errno : [EAGAIN] errno : [EAGAIN] errno : [EAGAIN] create [32754] threads
在上面的例子中,每一个线程开始后,什么也不作,马上就结束。 最后在个人环境下,只能建立 32754 个额外线程。线程
当线程被设置为分离状态后,线程结束时,它的资源会被系统自动的回收, 而再也不须要在其它线程中对其进行 pthread_join() 操做。code
下面咱们对代码作一些修改,让每一个线程在开始执行后,进行线程的分离, 而后看看执行后的结果。blog
void* start_thread(void * arg) { //注意,这里执行了线程的分离操做。线程分离也能够在线程建立的时候, //在属性里面设置 pthread_detach(pthread_self()); pthread_exit(NULL); return NULL; } int create_pthread(int n) { int try = 0; int i = 0; int err = 0; for(i = 0; i < n && try < 3; i++) { pthread_t pt; err = pthread_create(&pt, NULL, start_thread, NULL); if(0 != err) { if(EAGAIN == err) { printf("errno : [EAGAIN]\n"); } sleep(2); try ++; } } printf("create [%d] threads\n", i); return err; } int main(int argc, char * argv[]) { int n = 1 << 20; create_pthread(n); return 0; }
执行结果以下:资源
create [1048576] threads
能够看到,最后成功建立了 1M 个线程。而没有进行 pthread_join() 操做的时候,最多建立建立了 32754 个线程,缘由就是没有 detach 的线程,在其结束后,一些系统分配给它的资源还在被占用, 没有被回收,致使没法再建立新的线程了。而 detach 的线程,在其结束后, 它的资源会被系统进行回收,而后进行再利用。因此此次才能建立 1M 的线程。get
在 man pthread_create 手册中,能够看到关于一个线程的 detachd 状态和 joinable 状态的描述。其中说到,一个线程或者是 detachd 的状态,这样它结束后,资源会被系统 回收;或者是 joinable 状态,而且在另外一个线程里面被 pthread_join() 等待,pthread_join() 会回收它的资源。同步
咱们能够再作个实验,在建立完了一个 joinable 的线程后再使用 pthread_join() 等待它的结束, 回收它的资源,看看最多能够建立多少个线程。it
void* start_thread(void * arg) { pthread_exit(NULL); return NULL; } int create_pthread(int n) { int try = 0; int i = 0; int err = 0; for(i = 0; i < n && try < 3; i++) { pthread_t pt; err = pthread_create(&pt, NULL, start_thread, NULL); if(0 != err) { if(EAGAIN == err) { printf("errno : [EAGAIN]\n"); } sleep(2); try ++; } void *st = NULL; //这里等待一个线程的结束,并回收其资源 err = pthread_join(pt, &st); if(0 != err) { printf("errno = [%d]\n", err); sleep(2); try ++; } } printf("create [%d] threads\n", i); return err; } int main(int argc, char * argv[]) { int n = 1 << 20; create_pthread(n); return 0; }
执行结果:
create [1048576] threads
最后也是建立了 1M 个线程。
结论就是,在咱们编写多线程应用的时候,或者把一个线程的属性设置为 detachd 的状态,让系统来回收它的资源;或者是 joinable 状态,这样就可使用 pthread_join() 来阻塞的等待一个线程的结束,并回收其资源,而且pthread_join() 还会获得线程退出后的返回值,来判断线程的退出状态 。
同步地址:https://www.fengbohello.top/archives/linux-pthread-detach