Linux线程控制篇

Posted Suk-god

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux线程控制篇相关的知识,希望对你有一定的参考价值。

文章目录

1、线程创建

1.1 接口介绍

int pthread_create( pthread_t *thread,const pthread_attr_t *attrvoid*(*start_routine)(void*),void* arg)

参数

thread获取i线程标识符(地址),本质上就是线程独有空间的首地址
(独有空间指的是进程虚拟地址进空间的共享区中为该线程分配的空间)
返回值

attr线程的属性信息,一般传NULL,表示采用默认的线程属性

start_routine:函数指针,指向的是线程执行的入口函数
注意:线程执行起来的时候,从该函数开始运行,并不是main函数

arg:给线程入口函数传递的参数

返回值
成功 -->返回0
失败–>返回值小于0

1.2测试入口函数的传参

1.2.1 创建线程,查看线程的相关信息

通过pthread_create创建线程,让两个线程均不退出,通过命令查看进程的相关信息
code

#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<stdio.h>


using namespace std;

//线程的入口函数
void* pthread_start(void* arg)

    while(1)
    
        cout << "I am work thread!"<< endl;
        sleep(1);
    



int main()

    //1、创建一个进程
    pthread_t thread;
    int ret = pthread_create(&thread,NULL,pthread_start,NULL);
    if(ret < 0)
    
        perror("pthread_create");
        return 0;
    
    //2、主线程不退出,观察信息
    while(1)
    
        cout << "I am main thread!"<< endl;
        sleep(1);
    

    return 0;


(1)使用 pstack + 进程号 的方式查看调用堆栈,进而来获取线程的相关信息,具体如下图所示

(2)通过 top -H -p +进程号 来查看线程的信息

1.2.2 创建多个线程,通过传变量的值区分每一个线程

前提:创建5个线程,并且能够区分他们

1.2.2.1 传递临时变量

该程序仅仅在创建线程的基础上增添(修改)如下部分

分析结果:

对于上图中线程打印一样的标识符问题,如何解决?
我们可以让主线程每隔1秒打印一次。这样创建出来的线程就可以在 i 值还未更新的情况下得到CPU资源,进行打印;具体更改如下图:

此时再次观察现象

对于上图表述的不安全问题,应该如何解决呢?
线程访问了非法空间,归根结底就是i对应的空间失效了。因此,我们可以传递一个在整个进程中有效的变量。我们可以定义一个在main函数中有效的临时变量全局变量堆上动态开辟
但是,前两种方式不推荐,下面介绍第三种方式。

1.2.2.2 传递堆空间开辟的变量


输出结果:

1.2.3 入口函数传参的结论

1、不要传递临时变量给线程的入口函数
2、如果给线程入口函数传递了一个从上开辟的空间,让线程自行释放

2、线程终止

2.1 接口介绍

接口1:

void pthread_exit(void* retval)
参数: retval:线程退出时,传递给等待线程的退出信息
作用:谁调用谁退出

代码验证:

运行结果:

下面通过一个运行录屏来感受一下具体的执行过程:

pthread_exit

接口2:

int pthread_cancel(pthread_t thread)
参数: 被终止的线程的标识符
作用: 退出某个线程

要想退出一个线程,那么你必须知道该线程的线程标识符
下面先介绍一个接口,它的作用就是谁调用,谁就获取自己的线程标识符
pthread_t pthread_self(void)

🆗,下面我们测试3大类情况

情况1: 工作线程调用pthread_cancel接口终止自己


情况2:主线程调用pthread_cancel接口终止工作线程
分析代码

执行结果

通过pstack命令查看调用堆栈情况

情况3:主线程调用pthread_cancel接口终止主线程自己
(1)pthread_cancel接口后面有其他代码

通过ps aux | grep xxx来查看进程状态信息,我们发现在主线程退出之前,可以正常查看在主线程退出后,工作线程依旧在执行,但是却查不到任何相关信息

对于上面的结果,我们因该如何理解呢?

首先,我们在主线程退出之前,拿到它的线程号,然后在主线程终止后,使用top -H -p +线程号 来查看线程状态信息

就目前而看,我们的主线程在通过pthread_cancel来终止自己的时候,被终止的主线程会变成僵尸状态,而且只能通过top命令查看相关线程信息。

但是,主线程在调用pthread_cancel接口终止自己后,一定会让主线程变成僵尸状态吗?
我们带着这个疑问继续往下走

(2)pthread_cancel接口后面没有代码

在上述代码中将main函数末尾的while循环去掉

运行结果:

哎,我们发现,在这种情况下,整个程序会退出。
接下来,我们再来看一种情况
(3)工作线程可以正常退出

此时再来看运行结果,是什么样子呢?

通过top命令查看线程状态信息

🆗,以上就是对进程终止接口的理解。

3、线程等待

从上面的线程终止我们可以得到一个结论:
线程退出的时候也有可能变成僵尸状态,其原因是线程的退出状态信息没有被回收。因此我们就需要通过线程等待来回收退出线程的退出状态信息。

线程被创建出来的默认属性是joinable属性,退出的时候,依赖其他线程来回收资源(主要是回收线程使用到的共享区中的空间

3.1 接口介绍

int pthread_join(pthread_t thread,void** retval)

3.2 代码测试


4、线程分离

设置线程的分离属性,一旦线程设置了分离属性,则线程退出的时候,不需要任何人回收资源,OS可以回收

4.1 接口介绍

int pthread_detach(pthread_t thread);
参数thread:设置线程分离的线程标识符
可以自己对自己设置分离属性,也可以由其他线程对自己设置分离属性。

好的~
本次的控制篇内容到这里就结束了,路过的读友们记得留下足迹,多多交流┗|`O′|┛ !!

以上是关于Linux线程控制篇的主要内容,如果未能解决你的问题,请参考以下文章

Linux性能之内存篇

Linux线程概念篇

Linux线程概念篇

操作系统核心知识点整理--进程篇

Linux篇第十三篇——多线程(线程概念+线程控制)

Linux篇第十三篇——多线程(线程概念+线程控制)