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❄️…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
