线程理论篇1

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

什么是线程?

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

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

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

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

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

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

多线程与内存布局

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

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

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

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

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

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

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

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

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

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

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

线程池是如何工作的?

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

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

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

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

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

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

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

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

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

共享资源

代码区

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

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

线程之间共享代码区。

注意:

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

原因:

为了线程安全。


数据区

数据区存放全局变量。

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

堆区

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

栈区

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

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

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

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

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

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

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

只使用线程私有资源

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

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

主要分为几下一个点:

线程私有资源+函数参数

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

使用全局变量

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

线程局部存储

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

函数返回值

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能|推荐系统——工业界的推荐系统之序列建模

一、LastN特征 LastN:⽤户最近的𝑛 次交互(点击、点赞等)的物品ID。 对LastN物品ID做embedding,得到 𝑛 个向量。 把 𝑛 个向量取平均,作为⽤户的⼀种特征。 适⽤于召回双塔模型、…

【承装承修资质办理指南】广州市承装承修电力施工许可证四级资质申请所需材料详解

【承装承修资质办理指南】广州市承装承修电力施工许可证四级资质申请所需材料详解 广州市承装承修电力施工四级资质申请所需材料详解 在广州市申请承装承修电力施工四级资质,需要准备一系列详细的申请材料。这些材料不仅反映了企业的基本情况,还包括了企…

论文润色就用意得辑,打造学术精品新篇章

在学术的世界里,一篇优秀的论文如同璀璨的星辰,吸引着同行们的目光。然而,好的论文并非一蹴而就,它需要经过反复打磨、润色,才能焕发出夺目的光彩。在这个过程中,意得辑以其专业的服务、精湛的技巧&#xf…

四、Redis五种常用数据类型-List

List是Redis中的列表,按照插入顺序保存数据,插入顺序是什么样的,数据就怎么保存。可以添加一个元素到列表的头部(左边)或者尾部(右边)。一个列表最多可以包含232-1个元素(4294967295,每个列表超过40亿个元素)。是一种双向列表结构…

pytorch实现transformer(1): 模型介绍

文章目录 1. transformer 介绍2 Position Encoding2.1 位置编码原理2.2 代码实现3 Self-attention4 前馈层FFN5 残差连接与层归一化6 编码器和解码器结构1. transformer 介绍 Transformer 模型是由谷歌在 2017 年提出并首先应用于机器翻译的神经网络模型结构。机器翻译的目标是…

数字化校园的发展阶段

现代化技能虽然能很大程度上给人们日子带来很大的便利,可是许多新兴的科技被人们所接纳需求一个按部就班的进程。数字化学校也是如此。把高新科技引入到学校中,完全推翻之前的教育形式,关于学校来说也是一个巨大的挑战。所以数字化学校也不可…

怿星 × NI丨联合成功打造行业领先的L4自动驾驶数据回灌系统

怿星NI 联合成功打造行业领先的L4自动驾驶数据回灌系统(终版) 怿星与于NI(恩艾)公司联合打造的L4自动驾驶数据回灌系统,在支持多种数据同步回灌、实时模拟故障、高带宽数据传输的同时,具有视频链路扩展性高…

2024年钉钉群直播回放怎么保存

钉钉群直播回放下载插件我已经打包好了,有需要的自己下载一下 小白钉钉工具打包链接:百度网盘 请输入提取码 提取码:1234 --来自百度网盘超级会员V10的分享 1.首先解压好我给大家准备好的压缩包 2.再把逍遥一仙下载器解压出来&#xff0…

护眼台灯什么牌子好一点?五款专业护眼灯品牌排行分享

台灯作为家庭中不可或缺的桌面照明设备,在儿童和青少年的学习生活中扮演着至关重要的角色。对于这个年龄段的孩子来说,台灯的选择尤为关键,因为不恰当的照明可能对他们娇嫩的视力造成损害。护眼台灯什么牌子好一点?家长们在挑选台…

ERROR 1045 (28000) Access denied for user ‘root‘@‘IP‘(using password YES/NO)

查看权限 要查看MySQL用户的权限,您可以使用SHOW GRANTS语句。这将列出用户的权限,包括授予的权限和可以授予其他用户的权限。 以下是查看当前用户权限的SQL命令: SHOW GRANTS; 如果您想查看特定用户的权限,可以使用以下命令&…

delphi6直连redis服务(用lua脚本redis模块)

一、创建一个exe程序 创建一个exe程序,引用LuaRedis.pas单元(此单元自己封装的代码,目前主要封装了获取key和设置key/value功能),代码如下: unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls;type…

仅为娱乐,Python中如何重定义True为False?

在Python中,True 和 False 是内建的布尔常量,分别代表逻辑上的真和假。它们是不可变的,且在Python语言规范中具有特殊地位,不能被用户直接重定义。尝试给 True 或 False 赋予新的值是违反Python语言规则的,这样的操作会…

​在英特尔至强 CPU 上使用 Optimum Intel 实现超快 SetFit 推理

在缺少标注数据场景,SetFit 是解决的建模问题的一个有前途的解决方案,其由 Hugging Face 与Intel 实验室以及UKP Lab合作共同开发。作为一个高效的框架,SetFit 可用于对Sentence Transformers模型进行少样本微调。 SetFit 仅需很少的标注数据…

【JavaEE精炼宝库】计算机是如何工作的

目录 前言: 一、冯诺依曼体系 二、CPU基本知识 2.1 硬盘|内存|CPU关系: 2.2 指令: 2.3 CPU是如何执行指令的(重点): 2.4 小结: 三、编程语言 3.1 程序: 3.2 编程语言发展&a…

游戏全自动打金搬砖,单号收益300+ 轻松日入1000+

详情介绍 游戏全自动打金搬砖,单号收益300左右,多开收益更多,轻松日入1000 可矩阵操作。 项目长期稳定,全自动挂机无需人工操作,小白,宝妈,想做副业的都可以。

【链表-双向链表】

链表-双向链表 1.链表的分类1.1 分类依据1.2 常用类型 2.双向链表的2.1 双向链表的结构2.2 双向链表的操作2.2.1 **初始化**2.2.2 **尾插**2.2.3 **头插**2.2.4 **尾删**2.2.5 **头删**2.2.6 在pos位置之后插入数据2.2.7 删除pos节点2.2.8 查找2.2.9 销毁 1.链表的分类 1.1 分…

翻译技巧早操练-(减译法)

hello,大家好,今天继续来学习翻译的技巧篇第二个-减译法。 往期回顾 翻译早操练-(增译法)-CSDN博客 减译法的目的就是为了译入语表达的通顺,如果原文的一些表达直接翻译到译入语即累赘还不合时宜,那么可以采…

【启明智显技术分享】基于ESP32-S3方案的彩屏固件烧录指南

前言: 【启明智显】专注于HMI(人机交互)及AIoT(人工智能物联网)产品和解决方案的提供商,我们深知彩屏显示方案在现代物联网应用中的重要性。为此,我们一直致力于为客户提供彩屏显示方案相关的技…

主播美颜技术探秘:计算机视觉赋能的直播美颜SDK

今天,我们将深入探讨直播美颜技术背后的计算机视觉原理,以及赋能这一技术的直播美颜SDK。 一、计算机视觉与直播美颜 计算机视觉是一门研究如何使机器“看”的学科,它利用数字图像处理和模式识别等技术,使计算机能够模拟人类视觉…

STL速查

容器 (Containers) 图解容器 支持随机访问 stringarrayvectordeque支持支持支持支持 string 类 构造函数 string(); ------创建一个空的字符串 例如: string str;string(const char* s); ------使用字符串s初始化string(const string& str); ------拷贝构造 赋值操作…