Linux:线程概念、理解、控制
目录
一、认识线程
1.认识线程V1
2.认识线程V2
3.认识线程V3
4.认识线程V4
5.认识线程V5
二、线程控制
1.前言
2.创建线程
3.线程等待
4.线程终止
5.线程分离
三、线程理解
一、认识线程
1.认识线程V1
借用大多数计算机教材的话,线程是进程的一个执行分支,线程是CPU调度的基本单位。
多进程的缺点在于,每创建一个进程,就要创建一个PCB对象,一份地址空间,一张页表,想办法把这部分消耗缩小,就只需新建一份"PCB",地址空间和页表共用一份,代码部分再均分,比如有5个进程就把所有调度函数均分为5份,如此一来,CPU并不知道自己是执行多进程,只是在调度一个又一个PCB,而用户看来,CPU却是通过“多线程的方式”提高了效率。
2.认识线程V2
既然如此,多个进程有多个线程,系统中存在大量线程,必然需要描述、组织,然而,Linux下,并没有再单独定义线程结构体,而是用进程的结构体来模拟线程。
3.认识线程V3
- 重新认识进程
以前认识进程,这个进程是单执行流,用现在的话说就是内部只有一个线程。
现在认识进程,这个进程内部有多个线程,多个执行分支。
总结的看,进程是系统分配资源的单位,而线程是系统调度的单位,因此,往后理解进程,都要站在系统分配资源的角度去看。
4.认识线程V4
-
cpu调度角度
现在来看,有的进程只有一个执行流,cpu调度可以称为调度进程,而有的进程有多个执行流,cpu调度时称为调度线程。
Linux下,为了统一这种含糊不清的概念,把cpu调度的执行流统称为轻量级进程。线程<= 执行流 <= 进程。因此,cpu不再区分自己到底是在线程调度还是进程调度,都称为执行流。
- 内核级虚拟机技术
我们现在看待进程,它是操作系统分配资源的基本单位,可以认为是一个容器,那么如果一个进程所对应的代码部分是一个操作系统,意味着这个操作系统支持内核级虚拟机技术。
5.认识线程V5
- 页表
抛出一个问题,操作系统是怎么给多线程均分代码的?
第一个结论,内存本质上是有限个4KB的内存块,定义为数组,方便增删查改。
第二个结论,页表并不是简单的K-V映射,虚拟地址是有划分的,比如32位的虚拟地址,前10位是一个整体,中间10位是一个整体,后12位一般是页内偏移地址,而页表其实是多张页目录和多张页内偏移表。
第三个结论,多线程划分代码,其实就是让每一个线程拿到自己代码所在的n张页内偏移表。
二、线程控制
1.前言
ps -aL指令查看LWP(light weight process)。
ps -aL
过去,要么是单进程单执行流,要么是多进程多执行流,而学习多线程后,变成了单进程多执行流。
在内核层面,cpu调度的是一个又一个的LWP,只有轻量级进程。
Linux的内核代码没有线程结构体,只有轻量级进程的结构体定义。而在用户层面,要严格区分进程和线程。因此需要对内核的系统调用封装,于是有一个库叫 pthread库,这个库不属于内核代码,但是安装Linux操作系统时必须安装这个库。
2.创建线程
pthread_create

通过man手册可以得知,pthread_create这个函数用来创建一个新的线程,使用这个函数需要包含头文件<pthread.h>,由于在3号手册查到了这个函数,因此说明这个函数不是系统调用,是用户层封装的函数。此外,man手册提示编译和链接时要加特定选项-pthread。
void* HandleTask(void* args)
{//新线程std::string threadname = (char*)args;
} int main()
{//主线程pthread_t tid;pthread_create(&tid,nullptr,HandleTask,nullptr);return 0;
}
3.线程等待
在学习进程时,父进程要等待回收子进程。而线程这快,主线程也要等待新线程。
- 运行成功的多线程程序,主线程一定是最后运行结束的。主线程退出=进程退出,如果主线程的主体代码运行完毕,而新线程还在运行,则主线程需要等待新线程的执行结果。
pthread_join

第二个参数是输出型参数。
void* HandleTask(void* args)
{//新线程std::string threadname = (char*)args;int cnt =5;while(cnt){sleep(1);cnt--;}return (void*)111;
} int main()
{//主线程//创建pthread_t tid;pthread_create(&tid,nullptr,HandleTask,(void*)"name");//等待void* ret = nullptr;int cnt =10;while(cnt){sleep(1);cnt--;}int abc = pthread_join(tid,&ret);std::cout << "abc->" << abc << "new thread ret->" << (long)ret << std::endl;return 0;
}

没有发生异常的情况下,新线程的运行结果是可以通过参数手动获取到的。 如果任何一个线程出现异常(div 0, 野指针),都会导致整个进程退出! 同时说明多线程代码往往健壮性不好。
4.线程终止
- 线程return
- pthread_exit

哪一个线程调用这个函数,哪一个线程就被终止。
pthread_exit((void*)111);
- pthread_cancel

这个函数由主线程调用,用来发送终止信号。
//终止测试sleep(1);pthread_cancel(tid);

返回结果为-1,表明不是正常退出。
5.线程分离
pthread_detach

新线程做线程分离
pthread_detach(pthread_self());
主线程也可以主动分离掉新线程。
pthread_detach(tid);
- 线程分离后,到底发生了什么?什么样的情况需要线程分离?
每一个新线程默认是需要让主线程等待的,即主线程需要调用pthread_join函数。如果主线程不需要关心新线程的执行状态,那么就可以将这个新线程分离。新线程分离后,仍旧和其他线程共享资源,并且保留自己原来的私有资源,但是!如果主线程调用pthread_join去等待这个新线程,是会出错的,即被分离的线程意味着不再需要主线程等待。不管怎么设计程序,都建议让主线程最后一个退出。
三、线程理解
- 多线程相比多进程的优点
创建一个新线程的开销要比一个新进程小得多。
与进程的切换相比,线程切换时操作系统所做的操作要少得多。
1.切换线程时,需要切换上下文的寄存器相对少一点,切换线程,只需切换保存是哪一个线程的寄存器,而切换进程,还要多切换用来保持虚拟地址空间、页表的寄存器。
2.由于cpu缓存技术, 加载内存中代码时是一次性加载多行,而切换进程时,前后的代码内容更大概率不是在相邻存储,更大概率可能要刷新缓存,而多线程共享代码,大概率不需要刷新缓存。
- 线程私有的数据
1.线程的硬件上下文数据,本质是cpu寄存器的值,(这部分数据调度线程)
2.每一个线程都有自己的独立栈结构,(用来保证线程的常规运行)
- 线程共享的数据
1.代码部分、全局数据
2.文件描述符表、页表、进程地址空间等等
- C++11的多线程
语言层的多线程,其实是对pthread库的进一步封装。
- 更深的理解pthread_t
如何标识一个唯一的线程,Linux下有这样两种设计,在内核一层,即操作系统层面,并没有定义线程结构体,而是定义了一个LWP结构体,名为轻量级进程,等同于线程,内核里面LWP是唯一的。但是,Linux内核对线程的各种操作控制并不同于我们理论上学习的线程操作控制,因此,Linux又做封装,即封装好的pthread库,编译链接多线程程序时,必须要链接这个库,本质是第三方库,因为它既不属于语言,也不属于操作系统调用。
pthread_t就是pthread库里面定义的概念。
加载动态库,加载到物理内存后,经页表映射到虚拟地址空间中的共享区,在代码区中执行到pthread_t tid这行代码后,cpu则跳转到共享区(动态库已经加载)对应的定义处执行这行代码。
pthread动态库对线程做了管理,即定义了线程结构体,也使用数据结构控制。

每一个线程都有对应的结构体,这个结构体有的地方也叫tcb,而结构体的起始地址,就是pthread_t tid的值。
上文提到了线程私有的数据之一,就是独立栈结构。也是在pthread库里面的线程结构体中定义的,因为每一个线程都有对应执行的代码,可能会创建局部变量,这些变量就保存在这部分栈结构中。
线程局部存储:全局变量归所有线程共有,如果希望只写一份定义全局变量的代码,但是实际上却是多个进程各有一份数据,就可以用像下面这样定义,这些值保存在线程局部存储空间中。
__thread int IngTime = 0;相关文章:
Linux:线程概念、理解、控制
目录 一、认识线程 1.认识线程V1 2.认识线程V2 3.认识线程V3 4.认识线程V4 5.认识线程V5 二、线程控制 1.前言 2.创建线程 3.线程等待 4.线程终止 5.线程分离 三、线程理解 一、认识线程 1.认识线程V1 借用大多数计算机教材的话,线程是进程的一个执行…...
Postman如何流畅使用DeepSeek
上次写了一篇文章是用chatBox调用api的方式使用DeepSeek,但是实际只能请求少数几次就不再能给回响应。这回我干脆用最原生的方法Postman调用接口请求好了。 1. 通过下载安装Postman软件 postman下载(https://pan.quark.cn/s/c8d1c7d526f3),包含7.0和10…...
K8S下载离线安装包所需文件
下载相关文件 官网下载地址集合https://kubernetes.io/zh-cn/releases/download/ 下载相关镜像 官网镜像描述 所有 Kubernetes 容器镜像都被部署到 registry.k8s.io 容器镜像仓库。 容器镜像支持架构registry.k8s.io/kube-apiserver:v1.32.0amd64, arm, arm64, ppc64le, …...
探索Hugging Face:开源AI社区的核心工具与应用实践
引言:AI民主化的先锋 在自然语言处理(NLP)领域,Hugging Face已成为开源社区的代名词。这个成立于2016年的平台,通过提供易用的工具和丰富的预训练模型库,彻底改变了开发者使用和部署AI模型的方式。截至202…...
【操作系统】深入理解Linux物理内存
物理内存的组织结构 我们平时所称的内存也叫随机访问存储器也叫 RAM 。RAM 分为两类: 一类是静态 RAM( SRAM ),这类 SRAM 用于 CPU 高速缓存 L1Cache,L2Cache,L3Cache。其特点是访问速度快,访…...
npm 私服使用介绍
一、导读 本文主要介绍 npm 私服的使用,至于 npm 私服搭建的过程,可以看本人之前的文章《Docker 部署 verdaccio 搭建 npm 私服》 二、前置条件 npm私服地址:http://xxx.xxx.xxx.xxx:port/ 三、本地 npm 源切换 使用nrm,可以方…...
安全筑基,智能赋能:BeeWorks IM引领企业协同新纪元
在数字经济高速发展的今天,企业通讯系统已从单纯的信息传递工具演变为支撑业务创新的核心平台。传统通讯工具在安全性、智能化、协同性等方面的不足,严重制约着企业的数字化转型进程。BeeWorks IM系统以其创新的技术架构和智能化功能,正在重新…...
水务+AI应用探索(一)| FastGPT+DeepSeek 本地部署
在当下的科技浪潮中,AI 无疑是最炙手可热的焦点之一,其强大的能力催生出了丰富多样的应用场景,广泛渗透到各个行业领域。对于水务行业而言,AI 的潜力同样不可估量。为了深入探究 AI 在水务领域的实际应用成效,切实掌握…...
[JVM篇]垃圾回收器
垃圾回收器 Serial Seral Old PartNew CMS(Concurrent Mark Sweep) Parallel Scavenge Parallel Old G1 ZGC...
SQL Server:查看当前连接数和最大连接数
目录标题 **1. 查看当前连接数****使用系统视图****使用动态管理视图** **2. 查看最大连接数****通过配置选项****通过服务器属性** **3. 查看连接数的实时变化****4. 设置最大连接数****5. 查看连接的详细信息****6. 使用 SQL Server Management Studio (SSMS)****7. 使用 SQL…...
DeepSeek应用——与PyCharm的配套使用
目录 一、配置方法 二、使用方法 三、注意事项 1、插件市场无continue插件 2、无结果返回,且在本地模型报错 记录自己学习应用DeepSeek的过程,使用的是自己电脑本地部署的私有化蒸馏模型...... (举一反三,这个不单单是可以用…...
【第15章:量子深度学习与未来趋势—15.3 量子深度学习在图像处理、自然语言处理等领域的应用潜力分析】
一、开篇:为什么我们需要关注这场"量子+AI"的世纪联姻? 各位技术爱好者们,今天我们要聊的这个话题,可能是未来十年最值得押注的技术革命——量子深度学习。这不是简单的"1+1=2"的物理叠加,而是一场可能彻底改写AI发展轨迹的范式转移。 想象这样一个…...
多模态基础模型训练笔记-第一篇InternVL-g
一、TL;DR 将之前所有训练过的大模型的过程都总结和回忆一下,遇到的坑别忘了 二、问题记录 还是注意镜像的选择,选择社区最火的镜像,然后下载好对应的数据,主要显卡的选择,这个时候4090已经带不动了&…...
MyBatis:动态SQL高级标签使用方法指南
一、引言 目前互联网大厂在搭建后端Java服务时,常使用Springboot搭配Mybatis/Mybatis-plus的框架。Mybatis/Mybatis-plus之所以能成为当前国内主流的持久层框架,与其本身的优点有关:支持定制动态 SQL、存储过程及高级映射,简化数…...
使用grafana v11 建立k线(蜡烛图)仪表板
先看实现的结果 沪铜主力合约 2025-02-12 的1分钟k线图 功能介绍: 左上角支持切换主力合约,日期,实现动态加载数据. 项目背景: 我想通过前端展示期货指定品种某1天的1分钟k线,类似tqsdk 的web_gui 生成图形化界面— TianQin Python SDK 3.7.8 文档 项目架构: 后端: fastap…...
ubuntu 安装 Redis
一、下载 Redis 压缩包,wget http://download.redis.io/releases/redis-5.0.14.tar.gz 也可以去官网下载别的版本 https://redis.io 二、解压文件,tar -zxvf redis-5.0.14.tar.gz 三、编译安装(使用压缩包的方式需要编译安装)&…...
利用docker-compose一键创建并启动所有容器
简介 在开发复杂的分布式应用时,通常需要同时运行多个服务(如数据库、缓存、Web 应用等)。Docker Compose 提供了一种简便的方式来定义和运行多容器 Docker 应用程序。通过一个 docker-compose.yml 文件,您可以配置应用程序的服务…...
mysql开启gtid并配置主从
默认主从都开启了bin log. 1.主从都在/etc/my.cnf中加入并重启服务 gtid_mode ON enforce_gtid_consistency ON 2.在主库创建用户并授权 create user slave identified with mysql_native_password by 123456 mysql>GRANT REPLICATION SLAVE ON *.* to slave% identified…...
redis sentinel模式 与 redis 分片集群 配置
Redis 最低为5.0版本,以下为6.2.6版本信息。 模式 高可用性 数据分片 部署复杂度 适用场景 Sentinel 模式 高 无 中等 中小规模,需要高可用性 集群模式 高 支持 复杂 大规模,需要高…...
2025最新在GitHub上搭建个人图床,保姆级图文教程,实现图片高效管理
文章目录 🌍一. 图床❄️1.什么是图床❄️2.图床能解决什么问题? 🌍二. 在github上面创建图床🌍三. PicGo❄️1. PicGo介绍❄️ 2. 下载与安装❄️3. 配置图床 ❄️3.错误解决问题1问题2问题3问题4 🌍 四. Typora❄️…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
