Linux多线程基础(2):僵尸线程和资源回收

发布时间:2024年01月07日

在Linux多线程基础(1)中,我给大家介绍了多线程该如何创建,这一篇文章我们对僵尸进程以及如何回收线程进行讲解.

1.僵尸线程

僵尸线程的产生是因为主线程在子线程结束之前退出,导致子线程的状态无法被回收,从而形成了僵尸线程.

底层原理是线程有joinable(非分离)和unjoinable(分离)两种状态,创建线程时,默认属性是joinable.当线程在主函数终止时调用pthread_exit退出时,不会释放占用的内存资源,导致出现僵尸线程.

为了防止出现僵尸进程,就需要考虑到如何正确的进行资源回收.

1.1如何查看僵尸进程

终端中运行命令ps -el可以查看到系统中的所有进程。如果发现进程的状态为僵死(Z),则这些进程就为僵尸线程。

2.资源回收

线程资源回收的方法有4种:(PS:由于前两种方法用的频率较少这里着重介绍第3,4种方法的用法)

2.1.使用pthread_join()函数

如果线程没有设置unjoinable属性,可以使用pthread_join()函数阻塞当前线程,直到指定的线程结束为止,然后释放该线程的资源,最后在退出主函数。

2.2.设置分离属性

如果线程在创建时设置了unjoinable属性,那么当线程退出时,系统会自动回收线程所占用的资源。可以通过pthread_attr_setdetachstate()函数来设置线程的分离属性。

2.3.在主程序中使用pthread_detach函数

在主程序中调用pthread_detach函数将线程设置为分离状态,一旦一个线程被分离,其资源将会被系统自动回收,不需要其他线程来调用pthread_join函数等待其结束。定义如下:

int pthread_detach(pthread_t thread);

其中thread代表线程的标识符.

2.3.1举例说明

#include <pthread.h>    
#include<string.h>   
#include<stdio.h>    
#include<unistd.h>   
#include<stdlib.h>   
#include<iostream> 
  
void *pth1(void* str){  // 定义一个线程函数pth1,它没有参数并且返回一个void指针。  
    std::cout<<"第一个线程"<<std::endl;  
}  
  
int main(void){    
    pthread_t thread1;  // 定义一个pthread_t类型的变量thread1,用于存储线程ID。  
    pthread_create(&thread1,NULL,pth1,NULL);  // 使用pthread_create函数创建新的线程。新线程开始执行pth1函数,并将thread1的地址作为返回值。  
    pthread_detach(thread1);  // 使用pthread_detach函数将thread1线程分离。这意味着当该线程结束时,其资源会自动被系统回收,不需要其他线程来调用pthread_join。  
    std::cout<<"第一个线程退出"<<std::endl;   
    std::cout<<"主函数退出"<<std::endl;   
} 

2.4.在线程程序中使用pthread_detach函数

?在线程中调用pthread_detach函数将线程设置为分离状态。与方法3类似,但是传参稍有变化.

2.4.1举例说明

#include <pthread.h>  
#include<string.h>  
#include<stdio.h>  
#include<unistd.h>  
#include<stdlib.h>  
#include<iostream>  
void *pth1(void* str){  // 定义一个线程函数pth1,它没有参数并且返回一个void指针。  
    // 使用pthread_detach函数将当前线程分离。这意味着当该线程结束时,其资源会自动被系统回收,不需要其他线程来调用pthread_join。  
    pthread_detach(pthread_self());  
    std::cout<<"第一个线程"<<std::endl;  
}  
int main(void){  
    // 定义一个pthread_t类型的变量thread1,用于存储线程ID。  
    pthread_t thread1;  
    // 使用pthread_create函数创建新的线程。新线程开始执行pth1函数,并将thread1的地址作为返回值。  
    pthread_create(&thread1,NULL,pth1,NULL);    
    std::cout<<"第一个线程退出"<<std::endl;  
    std::cout<<"主函数退出"<<std::endl;  
    return 0; 
}

在终端运行程序

g++ -o phread pthread.cpp -lpthread
./phread


可以看到,主程序已经运行完退出后,子线程才运行结束.这是由于我们没有使用pthread_join()函数,系统并不会因为等待子线程运行而发生阻塞.

现在看看是否存在僵尸线程,在终端使用ps -el:

可以发现,并没有僵尸线程!

文章来源:https://blog.csdn.net/shnhe/article/details/135390023
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。