【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′|┛ !!

在这里插入图片描述

  • 17
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Suk-god

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值