Linux:线程控制

线程概念

线程(Thread)是进程(Process) 中的一个执行单元,是操作系统能够进行运算调度的最小单位。

线程也被称为“轻量级进程”(Lightweight Process, LWP)。

一个进程可以包含多个线程,这些线程共享该进程所拥有的全部资源(后续展开解释)。

轻量级进程

为什么认为线程是轻量级进程,主要有两方面:

1.线程创建:创建线程不产生新的进程地址空间,也就不需要创建对应的页表

2.线程切换:

(1)由于进程地址空间不同,进程切换时无法从高速缓存中读取数据,只能从较慢的内存中读取数据,而线程由于共享地址空间,更有可能直接从缓存中读取数据。

(2)由于进程地址空间不同,进程切换时会导致TLB失效,不能直接通过较快的TLB获得物理地址,而是需要通过较慢的页表来获得物理地址,而进程由于共享地址空间,即使在缓存中读取不到数据,也更有可能通过高速的TLB来获得物理地址进而访问内存

(3)相较于进程切换,线程切换时需要保存和恢复上下文更少

Linux下的线程

Linux下并没有为线程设计独立的概念和数据结构(即没有与PCB相对的TCB),线程和进程都是通过task_strcut来进行管理和调度的,线程和进程也都是通过同一个底层系统调用 clone() 来创建的。

不过为了内核对线程进行调度,线程有用于标识自身唯一性的ID:LWP(类型为pid_t)

使用命令ps -aL可以看到线程ID:

使用函数gettid()也可以获取线程ID:

线程资源共享

1.cpu分配给进程的时间片会均分给每一个线程

2.每个线程都有和进程一样的虚拟地址空间(这意味着理论上线程可以访问进程所有的代码和数据)。

3.此外,线程还共享⽂件描述符表 ,每种信号的处理⽅式,当前⼯作⽬录 ,⽤⼾id和组id。

线程独立

线程之间共享进程的所有资源,但为了各自完成不同的任务,还需要使得线程之间在一定程度上相互独立,这就需要每个线程持有一部分私有内容来标识自身唯一性并独立完成任务。

因此,每个线程拥有独立的:

线程ID,用于标识自身唯一性

信号掩码

调度策略和优先级

错误码

线程执行上下文,包括:

        程序计数器 (Program Counter): 指示当前执行指令的位置。

        寄存器集合 (Register Set): 存储线程运行时的临时数据。

线程栈 (Stack): 用于存储函数调用时的局部变量、参数、返回地址等。每个线程的栈是私有的,这是保证线程独立执行的关键。

线程局部存储(TLS):用于存储只能被该线程访问的全局变量

维护线程独立

pthread库通过数据结构struct_pthread来维护线程独立,struct_pthread位于共享区

而线程id就是该线程对应的struct_pthread的首地址(该线程id用于调用其他的线程API,属于进程级,并不是内核级的、用于标识线程唯一性的线程id),类型为pthread_t

线程栈

进程在创建时会复制父进程的栈区的地址空间,在使用时可以进行写时拷贝和动态增长 。

但由主线程⽣成的⼦线程,它的栈将不再是向下⽣⻓的,⽽是事先在共享区占用一个固定大小的空间。

线程局部存储

在进程内的全局变量被所有线程共享,有时我们希望一个全局变量被每个线程持有一个副本,这时就需要__thread来修饰该变量,此时该全局变量被每个线程独立地访问和操作

但是要注意:__thread只能用来修饰内置类型,不能用来修饰自定义类型。

编写如下代码进行测试:

​#include<pthread.h>
#include<unistd.h>
#include<iostream>__thread int v=100;void* task(void* arg)
{v+=(long long)arg;std::cout<<"线程"<<gettid()<<"的v是"<<v<<std::endl;return 0;
}int main()
{pthread_t t1,t2;pthread_create(&t1,NULL,task,(void*)1);  pthread_create(&t2,NULL,task,(void*)2);pthread_join(t1,NULL);pthread_join(t2,NULL);
}

输出结果:

可以看到两个线程对全局变量的操作互不干扰

Linux线程控制

线程创建

thread:返回线程ID

attr:设置线程的属性,attr为NULL表⽰使⽤默认属性

start_routine:是个函数地址,线程启动后要执⾏的函数

arg:传给线程启动函数的参数

返回值:成功返回0,失败返回错误码

线程终止

终止当前线程:

retval:用于输出线程要执行的函数的返回值

终止指定线程:

返回值:成功返回0,失败返回错误码

终止某一线程的三种方法:

1.从线程函数return。这种⽅法对主线程不适⽤,从main函数return相当于调⽤exit。

2. 线程可以调⽤pthread_ exit终⽌⾃⼰。

3. ⼀个线程可以调⽤pthread_ cancel终⽌同⼀进程中的另⼀个线程。

线程等待

主线程等待指定线程结束

thread:用于指定线程

retval:用于传出线程执行函数的返回值

线程分离

线程有两种状态:joinable和detached

默认情况下,新创建的线程是joinable的,线程退出后,需要主线程调用pthread_join,否则⽆法释放资源,从⽽造成系统泄漏。

如果不关⼼线程的返回值,可以调用pthread_detach,当线程退出时,⾃动释放线程资源。

适用于主线程为死循环的情景

thread:用于指定线程

注意:pthread_join和pthread_exit传参时不要传局部变量给retval,因为线程返回的值必须在线程结束后仍然有效。

多线程优缺点

优点:

1.创建与切换开销低
2.在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
3.对于计算密集型应用,为了能在多处理系统上运行,将计算分解到多个线程中实现
4.对于I/O 密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。

缺点:
1.性能损失
一个很少被外部事件阻塞的计算密集型线程往往无法与其他线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有额外的同步和调度开销。
2.健壮性降低
线程共享数据容易引发线程安全问题。
单个线程如果出现除零,野指针问题导致线程崩溃,进程也会随之崩溃。
3.缺乏访问控制
进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。
4.编程难度提高
编写与调试一个多线程程序比单线程程序困难得多  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/92055.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/92055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React 学习(4)

核心API———createRoot、render方法1.createRoot 方法是创建react的根容器&#xff0c;就是react元素的插入位置&#xff0c;插入的dom会被转化成react元素&#xff0c;根容器内的内容都会被react管理&#xff0c;原有dom都会被删除。react17 根容器创建、渲染方式&#xff0…

ASP .NET Core 8集成Swagger全攻略

Swagger (现在称为 OpenAPI) 是一个用于描述 RESTful API 的规范&#xff0c;ASP.NET Core 内置支持通过 Swashbuckle 库生成 Swagger 文档。以下是在 ASP.NET Core 8 中实现 Swagger 的完整步骤。1、添加Swagger NuGet 包dotnet add package Swashbuckle.AspNetCore2、添加Swa…

【iOS】源码阅读(六)——方法交换

文章目录方法交换什么是Method-Swizzling方法交换核心API**1. 获取方法对象****2. 添加/替换方法实现****3. 交换方法实现****4. 获取方法信息****5. 修改方法实现****使用示例&#xff1a;完整的 Method-Swizzling 流程****注意事项**使用方法交换注意事项线程安全方法交换的影…

mysql运维问题解决:MySQL主从延迟(锁阻塞与读写分离)

小亦平台会持续给大家科普一些运维过程中常见的问题解决案例&#xff0c;运维朋友们可以在常见问题及解决方案专栏查看更多案例 问题概述 告警事件&#xff1a; 2023-07-28 03:31:39.571 首次触发主从延迟告警&#xff08;延迟1515秒&#xff09;2023-07-28 07:41:37 告警解除…

SSH 密钥

什么是 SSH 密钥 SSH 密钥就像是你电脑的“身份证”和“钥匙”&#xff0c; 用来安全登录另一台电脑&#xff08;服务器&#xff09;&#xff0c;而不需要每次输入密码。SSH 密钥是一种安全登录远程服务器的方式&#xff0c;由一对加密的“钥匙”组成&#xff1a;一个公钥 一个…

st-Gcn训练跳绳识别模型一:数据标注工具和标注流程

目录 工具展示和使用说明 工具标注后文件展示说明 json转换成单个npy文件 数据获取补充 工具展示和使用说明 文件名labelV.py集于PySide6实现&#xff1a; 通过选择视频来选择你要标注的视频&#xff0c;然后选择保存路径&#xff1a; 然后视频两个类别。当你看见视频中的人…

springboot跨域问题 和 401

springboot跨域问题 和 401 1.跨域import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotatio…

构建直播平台大体的流程

✅ 直播流程完整链路&#xff08;基于 SRS OBS 前后端&#xff09;&#x1f9cd;‍♂️ 用户操作流程&#xff1a;✅ 用户登录系统&#xff08;前端&#xff09;系统中校验用户身份&#xff08;JWT 等&#xff09;后端可能校验权限&#xff0c;比如“是否有开播资格”✅ 用户…

KOSMOS-2: 将多模态大型语言模型与世界对接

温馨提示&#xff1a; 本篇文章已同步至"AI专题精讲" KOSMOS-2: 将多模态大型语言模型与世界对接 摘要 我们介绍了 KOSMOS-2&#xff0c;一种多模态大型语言模型&#xff08;MLLM&#xff09;&#xff0c;赋予了模型感知物体描述&#xff08;例如&#xff0c;边界框…

协作机器人操作与编程-PE系统示教编程和脚本讲解(直播回放)

协作机器人操作与编程-PE系统示教编程和脚本讲解本次讲解主要围绕协作机器人PE系统的操作与编程展开&#xff0c;内容涵盖软件安装、虚拟机配置、手动操作、在线编程、变量设置、网络通信及标定方法等方面。以下是主要内容要点提炼&#xff1a; 软件安装与虚拟机配置 需从官网下…

【前后端】Node.js 模块大全

用到的全部总结在这里&#xff0c;不定期更新 链接 node一本通 包括&#xff1a; express path fs/ process/ os/ http/ mysql/mongoose/ express-jwt/jsonwebtoken/ dotenv/ multer/ swagger/ cors/ nodemon (docker篇有)常用模块 内置 fs 文件系统操作&#xff08;读写、重命…

双8无碳小车“cad【17张】三维图+设计说名书

基于MATLAB的双八无碳小车轨迹仿真及其结构设计 摘 要 本文设计的基于MATLAB的无碳小车来自于全国大学生工程训练能力竞赛&#xff0c;依据绿色环保&#xff0c;设计一种通过重力势能转换成动能来驱动小车行走的装置。通过分析任务要求&#xff0c;本文完成了小车的三维结构设计…

视觉大模型离线部署全流程优化:从微调技术到工程实践

视觉大模型离线部署全流程优化&#xff1a;从微调技术到工程实践 一、视觉大模型离线部署概述 1.1 视觉大模型的应用场景与挑战 视觉大模型在物体检测、图像生成、图像描述等领域展现出强大能力&#xff0c;已成为人工智能领域的研究热点和产业应用焦点(5)。随着技术的发…

Vue中组件的生命周期

组件的生命周期生命周期、生命周期函数、生命周期钩子vue2的生命周期创建&#xff08;创建前的生命周期函数 beforeCreate &#xff0c;创建完毕created&#xff09;挂载&#xff08;挂载前beforeMount&#xff0c;挂载完毕mounted&#xff09;//把组件放在页面中更新&#xff…

securecrt连接服务器报错 Key exchange failed 怎么办

新买了一台阿里云机&#xff0c;用securecrt去连接&#xff0c;如下报错这个错误表明你的 SSH 客户端与服务器之间无法就密钥交换方法和主机密钥算法达成一致&#xff0c;导致连接失败。这通常是由于客户端和服务器支持的加密算法集不匹配造成的。 解决方式 编辑服务器的/etc/s…

用协议分层模型实战:从物理层到应用层的STM32协议栈开发

目录 1. 揭开协议栈的神秘面纱:从STM32到分层思维 STM32的硬件优势 本章实战:点亮物理层的第一步 2. 数据链路层:让STM32学会“打包”和“拆包” 以太网帧的那些事儿 实战:解析以太网帧 3. 网络层:让STM32学会“找路” LwIP的快速上手 实战:实现一个简单的Ping …

微服务基础环境搭建-centos7

文章目录1、安装docker1.1、安装步骤1.2、docker常用命令2、安装Nginx3、Docker安装Mysql4、Docker安装Redis5、安装Nacos5.1、Nacos的作用5.2、单体服务安装6、安装RocketMQ服务6.1 MQ的作用6.2 RocketMQ的基础服务架构6.2、安装RocketMQ服务6.3、安装dashboard面板服务6.4、R…

Netty知识点

一、Netty的零拷贝机制 零拷贝的基本理念&#xff1a;避免在用户态和内核态之间拷贝数据&#xff0c;从而降低 CPU 占用和内存带宽的消耗除了系统层面的零拷贝。 1、FileRegion 接口 FileRegion 是 Netty 提供的用于文件传输的接口&#xff0c;它通过调用操作系统的 sendfile 函…

Kafka的基本使用

目录 认识Kafka 消息队列 消息队列的核心概念 核心价值与解决的问题 Kafka ZooKeeper Kafka的基本使用 环境安装 启动zookeeper 启动Kafka 消息主题 创建主题 查询主题 修改主题 发送数据 命令行操作 JavaAPI操作 消费数据 命令行操作 JavaAPI操作 认识Kafka…

Flink2.0学习笔记:Table API SQL

stevensu1/EC0720 表 API 和 SQL# 表 API 和 SQL——用于统一流和批处理 加工。表 API 是适用于 Java、Scala 和 Python 的语言集成查询 API&#xff0c;它 允许组合来自关系运算符的查询&#xff0c;例如 selection、filter 和 join in 一种非常直观的方式。Flink 的 SQL 支…