【Linux】信号(二):Linux原生线程库相关接口

【Linux】信号的控制使用

在上次的博客中主要讲解了什么是线程

这次的博客主要是带大家把线程的相关接口简单的使用一下

这次博客的篇幅不长,就单纯了解接口的,之后的博客才会来主要剖析线程

首先在Linux中有一个原生线程库

Linux中没有线程的概念,但是用户肯定是需要线程这个东西的

所以说Linux中有一个原生线程库 (基本上所有的Linux中都有)

叫做pthread.h,正是这个原生线程库给用户提供了Linux中的线程的这个概念

这个博客接下来就是带大家来认识一下比较常用的原生线程库中的接口的

一.线程的创建

pthread_create()接口

这里带大家来认识一下对应的参数

大致就是这么个用处

cpp 复制代码
#include<iostream>
#include<pthread.h>
#include<unistd.h>
void* run_pthread(void* argv)
{
        std::cout<<*(int*)argv<<std::endl;
}

int main()
{
        pthread_t lwp_id;
        int i=10;
        pthread_create(&lwp_id,nullptr,run_pthread,(void*)&i);
        sleep(5);



}

这边随便写一个用用

这里可能有人注意到,为什么要sleep(5)

众所周知,主线程和子线程是同时运行的,创建完子线程,这个主线程就直接结束了
所以说这个int i的变量直接就在主线程中被销毁了

所以说接下来就引出了线程等待

二.线程等待

1.为什么要线程等待?

首先什么是线程等待?

我们在什么地方看到过等待?

就是我们以前在进程博客中写过的,进程等待

还记得为什么父子进程要等待吗

因为你父进程把子进程生了下来,你不能不管啊

如果你父进程结束了,子进程没有人来回收,那就变成孤儿进程和僵尸进程了

映射到我们线程,其实原理也差不多

但是还是有一点不一样的。
进程是独立的 ,但是线程是进程的执行流
当主线程结束后 (也就是main函数结束),所有的子进程也会中断

那为什么要等待呢?
1.资源回收

线程退出时,其栈内存和系统资源不会自动释放,需要等待来正确释放

2.同步执行顺序:

确保某些操作在其他线程完成后执行

3.获取返回值:

就是进程执行的结果

所以说我们要介绍一个线程等待的接口

可以接受线程执行结果的返回值 ,而且是阻塞等待

2.pthread_join()


接口大致就是这样的思路

cpp 复制代码
#include<iostream>
#include<pthread.h>
#include<unistd.h>
void* run_pthread(void* argv)
{
        std::cout<<*(int*)argv<<std::endl;
}

int main()
{
        pthread_t lwp_id;
        int i=10;
        pthread_create(&lwp_id,nullptr,run_pthread,(void*)&i);
        pthread_join(lwp_id,nullptr);
}

这里我们把sleep,直接换成了 pthread_join(lwp_id,nullptr);

因为是阻塞等待,只会等待子线程处理完,才会结束,所以i的生命周期还在,没有被销毁

这里其实一直有个编译警告,这里没有放出来

意思就是子线程没有返回值

这里就带大家把这个等待线程的接受子线程返回值给用用

cpp 复制代码
#include<iostream>
#include<pthread.h>
#include<unistd.h>
void* run_pthread(void* argv)
{
        std::cout<<*(int*)argv<<std::endl;
        return (void*)(intptr_t)1;
}

int main()
{
        pthread_t lwp_id;
        int i=10;
        pthread_create(&lwp_id,nullptr,run_pthread,(void*)&i);
        void* ret;
        pthread_join(lwp_id,&ret);
        std::cout<<"running end= "<<(intptr_t)ret<<std::endl;
}


这个intptr_t是C++库中的一个整数类型,它专门用于安全地存储指针值
intptr_t 是一个有符号整数类型,其大小能够容纳任何有效的指针值

子线程执行结果是通过void*来返回的
所以说我们在子进程中返回void*

然后在pthread_join中接受的返回值是void()**

二级指针就是接受一级指针的地址的 ,所以用取地址

这里要注意一点:
为什么在pthread_join中不考虑异常,只考虑返回值

因为线程出现异常问题,整个线程都完了,所以只有进程才会去考虑异常

三.线程中止

这个其实就是如何返回进程的返回值的:

1.return

这个我们在上面的代码中使用过了,接下来就随便用用下一个

2.pthread_exit

这个其实就当return用就行

cpp 复制代码
#include<iostream>
#include<pthread.h>
#include<unistd.h>
void* run_pthread(void* argv)
{
        std::cout<<*(int*)argv<<std::endl;
        pthread_exit((void*)(intptr_t)1);
}

int main()
{
        pthread_t lwp_id;
        int i=10;
        pthread_create(&lwp_id,nullptr,run_pthread,(void*)&i);
        void* ret;
        pthread_join(lwp_id,&ret);
        std::cout<<"running end= "<<(intptr_t)ret<<std::endl;
}

五.线程应用

C++自带多线程

c++11也已经支持多线程

cpp 复制代码
#include<iostream>
#include<thread>

void run_code()
{
        std::cout<<"i am ok"<<std::endl;


}

int main()
{
        std::thread t(run_code);
        t.join();
        return 0;

}

但其实在Linux中的C++的多线程也是封装的,底层用的还是pthread的原生线程库

因为你编译的时候,还是需要-lpthread来链接原生线程库

不管是什么语言,底层都是调用的原生线程库,进行封装的
推荐使用语言自带的,因为具有可移植性

相关推荐
wuminyu5 小时前
JVM规范学习总结:解释器与JIT编译器如何处理JVM字节码
java·linux·c语言·jvm·c++
海宇AI6 小时前
零信任架构实战:基于海宇个人风险报告构建自动化分期商城信用额度初审网关
运维·人工智能·架构·自动化
IMPYLH6 小时前
Linux 的时间为什么会被拨回去
linux·运维·服务器
2601_963282777 小时前
寒地窄带通信工程实践:黑龙江哈尔滨对讲机选型、组网与合规运维总结
运维·服务器·网络
叼烟扛炮8 小时前
[Git 实战] 学习笔记:从生成 SSH 密钥到解决 TortoiseGit 推送报错全指南
linux·运维·笔记·git·学习
xbzb8 小时前
OpenStack 网络管理(理论):Linux 网络虚拟化是 Neutron 的地基
linux·服务器·网络·openstack·network·neutron
我要见SA姐19 小时前
GitHub Actions 自动化:5 个真实运维提效案例
运维·数据库·机器学习·oracle·回归
Android系统攻城狮9 小时前
Linux FFmpeg深度解析之avcodec_flush_buffers调用流程与实战(十九)
linux·运维·服务器·ffmpeg·车载音视频·ffmpeg音视频进阶
水饺编程11 小时前
第2章:Linux 基础,解压缩【.tar.bz2】压缩包文件
linux·c语言·汇编
Y38153266211 小时前
用 httpx 写 SerpBase 异步客户端:连接池与超时配置
运维·服务器·数据库