线程理论篇1

news2025/2/27 23:16:26

本章问题:什么是线程?线程的使用场景?什么是线程池?线程池是如何工作的?线程池共享了哪些资源?线程安全代码怎么写?什么是线程安全?

什么是线程?

线程是为了提高进程的效率。进程的地址空间中保存了cpu执行的机器指令以及函数运行时的堆栈信息,要想让程序运行起来,就要不拿main函数的第一条机器指令地址写入pc寄存器,从而形成一个指令的执行流。

进程的缺点在于只有一个入口函数,就是main()函数。因此进程中的机器指令一次只能被一个cpu执行,有没有办法让多个cpu执行同一个进程中的机器指令呢?

当然,pc寄存器既然可以指向main()函数,也可以指向其他函数,从而创建一个新的执行流。

至此,一个进程内可以有多个入口函数,也就是一个进程存在多个执行流。

更关键的是,这些执行流共享同一个进程地址空间,因此也不再需要进程间通信了。

对于每一条执行流,我们都称其为“线程”。

多线程与内存布局

函数在执行时依赖的信息包括函数参数局部变量返回地址等信息,这些信息都被保存在相应的栈帧中。每个函数在运行时都有自己的栈帧,随着函数的调用,以及返回,这些栈帧按照先进后出的顺序增长或减少。栈帧的增长或减少形成地址进程空间中的栈区

在线程这个概念没有出现时,一个进程中只有一个执行流,因此只有一个栈区,现在有了线程之后就有了多个执行流,每个执行流都要有自己的栈区

言而总之,想说的就是创建线程是要消耗进程内存看空间的,这一点值得注意。

线程的使用场景(引出线程池的概念)

从生命周期来看,线程要处理的任务有两种:长任务,短任务。

对于长任务没有什么好说的。收到哦一个请求就创建一个线程来处理任务,处理完成之后销毁该栈帧即可。

对于短任务来说,短任务的生命周期短,如一次网络请求一次数据库查询等。这类任务往往判断着一个特点:量大。

(1)对于每次收到一个短任务就创建一个线程,等周期结束再消耗栈帧,必然会消耗大量的时间。(线程的创建和销毁是会消耗时间的)

(2)每个线程都有独立的栈区,当创建大量线程时会消耗过多的内存。

(3)大量线程会使线程的切换开销增加。

因此我们可以提前创建一批线程,有任务就交给做这些线程进行处理。不需要频繁的创建,销毁,没任务就让这些线程的任务队列中阻塞等待。

线程池是如何工作的?

有了任务,有了线程,有了线程池,怎么把任务提交给线程池中的线程呢?

我们用数据结构中的队列来维护线程池。

在没有任务的时候线程池中的线程会在任务队列中阻塞等待,当生产者向任务队列中写入数据课后,线程池中的某个线程会被唤醒,该线程会从任务队列中取出上述结构体并执行该结构体中handle指向的处理函数:

线程到底共享了哪些进程资源?

在讨论线程共享了哪些资源前我们先想想线程都有哪些资源。

线程其实就是函数的执行,那么函数的执行都有哪些信息呢?

函数在运行时信息保存在栈帧中,栈帧组成了栈区,栈帧中保存了函数的返回值调用其他函数的参数该函数使用的局部变量该函数适用的寄存器信息等。

所属线程的栈区,栈指针,程序计数器,以及执行函数时使用的寄存器信息都是线程私有的。

剩下的堆区,数据区,代码区都是共享的:

共享资源

代码区

代码区保存的是程序员写的代码,更准确的是编译后生成的可执行机器指令。

这些机器指令被存放在可执行程序中,程序启动时加载到进程的地址空间中。

线程之间共享代码区。

注意:

代码区只是只读的 ,任何线程在程序运行期间都不能修改代码区。

原因:

为了线程安全。


数据区

数据区存放全局变量。

所有线程都可以共享该全局变量。
 

堆区

只要知道变量的地址(指针),任何一个线程都可以访问指针指向的数据。

栈区

我们前面说栈区是线程的私有区,为什么这里又说栈区可以被线程共享呢?

首先我们要知道前面说的栈区是私有的是针对不同进程的线程之间来说的。因为不同进程的地址空间是相互隔离的,没有办法直接访问属于另一个进程地址空间中的数据。但是同一个进程的不同线程之间没有这种保护,因为一个线程可以访问另一个线程的栈区。

什么是线程安全?线程安全的代码到底是怎么编写的?

线程安全的定义:给定一段代码,不管其在多少个线程中被调用,也不管这些线程按照什么顺序调用,当其都能给出正确结果时,我们就称这段代码是线程安全的。

例如上面的代码段,像这种无论用多少线程同时调用,怎么调用,什么时候调用都会返回2,这段代码就是线程安全的。

线程安全的代码怎么编写:(1)线程使用自己的私有资源,能实现线程安全。

(2)线程使用共享资源时,必须要保证不影响其他线程。

只使用线程私有资源

最简单的,只要我们写一段代码不依赖任何全局变量,不依赖任何函数,且使用的局部变量都是线程的私有资源,那么写的代码就一定是线程安全,例如:

但是,在实际开发中我们肯定会调用外部函数和全局变量的,因此,我们重点还是要看一下使用共享资源时如何写出线程安全的代码。

主要分为几下一个点:

线程私有资源+函数参数

当传入参数为指针时要注意:

使用全局变量

如果写的代码没有修改全局变量,那么写出来的代码就是线程安全的,否则就不是。

线程局部存储

线程的局部存储是在全局变量前_thread关键词,此时线程就是安全的了。

此时,globbal_num这个全局变量就变为了当前线程的局部私有变量,不会影响其他线程。

函数返回值

如果函数返回的是值,一般都是安全的,如果函数返回的是指针,可能比较危险。

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

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

相关文章

紧跟生成式AI暴雨发布新时代推理服务器

近日,暴雨发布最新训推一体AI服务器,以大容量内存和灵活的高速互连选项满足各种AI应用场景,最大可能支持扩展插槽,从而大幅提升智能算力性能,以最优的性能和成本为企业的模型训练推理落地应用提供更好的通用算力。 AIG…

重学java 31.API 3.数学相关类

看似不起波澜的日复一日,会突然在某一天让人看到坚持的意义 —— 24.5.8 数学相关类 1.Math类介绍 1.概述 数学工具类 2.作用 主要用于数学运算 3.特点 a、构造方法私有了 b、方法都是静态的 4.使用 类名直接调用 static int abs(int a) ->求参数的绝对值 stat…

ChatGLM-Math:强化数学能力

大型语言模型(LLM)在文本摘要、问答和角色扮演对话等语言任务上表现出色,在数学推理等复杂问题上也具有应用潜力。 但目前提高 LLM 数学问题解决能力的方法,往往会导致其他方面能力的下降。例如RLHF的方法,虽然可以提…

软考系列必过资料分享-系统架构师-系统分析师-信息系统项目管理师

建议,写在前面 知识点是公用的,原则上不分新旧。每年会有少部分的题目切合当前时间段(也是通过旧的知识演变的) 信息系统项目管理师证书 系统架构师证书 系统分析师证书 资料分享 关注公众号 回复 信息系统项目管理师资料 即可获取信息系统项目管理师资…

翻译《The Old New Thing》 - The new scratch program

The new scratch program - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20050422-08/?p35813 Raymond Chen 2005年4月22日 译注:此篇是 翻译《The Old New Thing》 - The scratch program 姊妹篇,对 scratch 程序作…

【通信】电子科协通信专题

数字通信 最直观的通信方式-基带通信 问题:①无限大的带宽②天线体积

[QTcreator]QT中一个cpp文件如何使用另一个界面的控件

在工作过程中将函数封装成一个类放入一个cpp文件中,但是里面的函数需要运用到其他界面的控件,以此记录昨天的学习。 首先明确一下我需要在vtkfuntion.cpp使用mainwindow.ui中的qvtkwidget控件 step1:更改mainwindow.h 添加需要应用的文件的头文件&…

python:画饼图

我现在因工作需要在写一篇中文文章,领导要我用python处理数据和画图,那我也刚好学习一下python画图。 import matplotlib.pyplot as plt # 饼图数据 labels [A, B, C, D] sizes [15, 30, 45, 10] # 每个部分的大小 # 绘制饼图 plt.figure(figsize(6,…

Spring Web MVC 快速入门

🎥 个人主页:Dikz12🔥个人专栏:Spring学习之路📕格言:吾愚多不敏,而愿加学欢迎大家👍点赞✍评论⭐收藏 目录 什么是Spring MVC? MVC模式介绍 ​编辑学习Spring MVC…

开源数据可视化大屏对接表单数据实践!

如果你需要一个表单系统,进行数据收集;可以使用tduck填鸭进行私有化部署,进行表单制作,完成数据收集。 在实际业务中,往往需要将收集的数据进行展示或分析;此时就可以使用表单数据推送到TReport中&#xf…

详细解读性能测试指标(性能指标、CPU、内存、负载、磁盘)

🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 性能测试指标是衡量系统性能的评价标准,常用的系统性…

remmina无法连接远程桌面,Remmina无法连接远程桌面的原因与解决办法

在解决Remmina无法连接远程桌面的问题时,我们需要考虑多种可能的原因,并采取相应的解决办法。以下是一些常见的原因及其对应的解决方案: 1、网络问题 原因:不稳定的网络连接或中断可能导致无法建立远程桌面连接。 解决办法&#x…

环保设备统一管理系统

在环保意识日益增强的今天,企业如何有效管理环保设备,确保其正常运行,减少环境污染,成为了一个重要议题。HiWoo Cloud平台以其独特的环保设备统一管理系统,为企业提供了一套完整的解决方案,帮助企业实现绿色…

量化地形处理

1: 量化地形切片:GDAL查询数据;CTB算法转mesh;高度图需要和周围高度图边界做高度融合,四顶点需要做平均值融合;法线想要在前端显示正确必须将mesh坐标转为4326或者3857; 这个使用开源即可:cesi…

肖特基二极管 SOD-123HE封装 散热性好

肖特基二极管发热问题,一直是众多电子工程师常讨论的话题之一。在实际应用中,肖特基二极管发热量真地不容忽视,其发热量大小和实际工作电流和压降大小有关。针对肖特基二极管发热问题,二三极管厂家东沃电子DOWOSEMI有几点建议&…

怎么编辑百度百科个人词条

辑百度百科个人词条是一个相对复杂的过程,需要遵循一定的步骤和规则。以下是百科优化网整理的编辑百度百科个人词条的步骤和注意事项。 1. 确定编辑资格 百度百科个人词条的编辑权主要赋予那些具有一定影响力的公众人物,或者是有一定“身份”的人物&…

STM32 GPIO介绍

每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL, GPIOx_CRH),两个32位数据寄存器 (GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。 通过软件配置寄…

idea修改maven项目名称及子模块名称

一、修改目录名称 shift F6修改目录,选择“rename module and dictionary”。![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/43efd9c6af6e43ad9656455db94b37a2.png)二、修改子项目pom的 三、修改父项目pom的 四、刷新maven项目

SpringBoot:SpringBoot:实战项目TILAS智能学习辅助系统1.3

登录认证 需求:输入登录请求服务器判断用户的用户名和密码 //控制层 PostMapping("/login")public Result login(RequestBody Emp emp);Overridepublic Result login(Emp emp) {Emp emp1 empService.selectLogin(emp);if(emp1 null){System.out.println("用…

企业百度百科词条怎么修改

在进行企业百度百科词条的修改前,首先需要做好以下准备: 注册并登录百度账号:只有注册并登录了百度账号,你才能进行词条的编辑和修改。 熟悉百度百科编辑规则:了解百度百科的编辑规则,包括内容要求、格式规…