线程理论篇1

news/2024/5/20 4:27:02

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

什么是线程?

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

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

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

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

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

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

多线程与内存布局

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

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

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

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

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

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

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

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

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

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

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

线程池是如何工作的?

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

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

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

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

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

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

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

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

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

共享资源

代码区

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

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

线程之间共享代码区。

注意:

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

原因:

为了线程安全。


数据区

数据区存放全局变量。

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

堆区

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

栈区

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

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

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

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

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

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

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

只使用线程私有资源

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

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

主要分为几下一个点:

线程私有资源+函数参数

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

使用全局变量

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

线程局部存储

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

函数返回值

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


http://www.mrgr.cn/p/78533763

相关文章

Go pprof 认知到实践

快速开始 测试环境:go version go1.22.2 windows/amd64,源代码开源在 https://github.com/oldme-git/teach-study/tree/master/golang/base/pprof 在正式开始之前,请确保安装 graphviz,这一步不可省略,它可以协助 pprof 生成更直观的数据分析图。可以参考官方网站的安装方…

C#与PLC变量在数据交互上的一些探索

1. 基于C#的数据交互 A. S7,using S7.Net,后文读写数据时二次封装过S7协议,这里暂且不表,只列举S7协议最原始的应用。new一个PLC对象//idenfy basic link paramsprivate string plc_ip;private CpuType plc_type;private short plc_rack, plc_slot;public Plc my_plc;my_plc…

三角函数之诱导公式

壹如上图: \[\begin{eqnarray} 已知: \enspace AC=\sin\alpha,BC=\cos\alpha \\ \\ \\ \sin\left(\frac{\pi}{2}-\alpha\right)=\frac{AD}{AB}=\frac{BC}{AB}=\cos\alpha \\ \\ 诱导公式组0.1: \enspace \sin\left(\frac{\pi}{2}-\alpha\right)=\cos\alpha \\ \\ \\ \cos\left(…

解锁AI的神秘力量:LangChain4j带你步入智能化实践之门

关注微信公众号 “程序员小胖” 每日技术干货,第一时间送达! 引言 在数字化转型的浪潮中,人工智能(AI)正逐渐成为推动企业创新和增长的关键力量。然而,将AI技术融入到日常业务流程并非易事,它…

ubuntu下多jdk环境轻松却换

在实际coding生活中,维护老项目与开发新项目常是并行的。快速企业java开发jdk版本,收首先要解决的问题。 今天看到一篇Blog,参考配置后完美实现了一键快速切换,nice!!!!!! 环境: 1、ubuntu 22 2、openjdk1.8、openjdk17 具体操作步骤: 1、安装openjdk(略),安装位…

CentOS 7 部署 NET6.0 项目过程

1、环境配置NET6.0 环境搭建主要是SDK 和 runtime 的安装,下图截自官网说明了SDK 和 runtime 的关系CentOS7 安装SDK 方法第一步:rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm第二部:yum install dotnet-sdk-6.0也可以只安装对应的…

接入大量设备后,视频汇聚系统EasyCVR安防监控视频融合平台是如何实现负载均衡的?

一、负载均衡 随着技术的不断进步和监控需求的日益增长,企业视频监控系统的规模也在不断扩大,接入大量监控设备已成为一项常态化的挑战。为确保企业能够有效应对这一挑战,视频汇聚系统EasyCVR视频融合平台凭借其卓越的高并发处理能力&#x…

软件杯 深度学习花卉识别 - python 机器视觉 opencv

文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 &a…

细说夜莺监控系统告警自愈机制

虽说监控系统最侧重的功能是指标采集、存储、分析、告警,为了能够快速恢复故障,告警自愈机制也是需要重点投入建设的,所有可以固化为脚本的应急预案都可以使用告警自愈机制来快速驱动。夜莺开源项目从 v7 版本开始内置了告警自愈模块,本文将详细介绍告警自愈的原理和实现。…

掌握Android Fragment开发之魂:Fragment的深度解析(上)

Fragment是Android开发中用于构建动态和灵活界面的基石。它不仅提升了应用的模块化程度,还增强了用户界面的动态性和交互性,允许开发者将应用界面划分为多个独立、可重用的部分,每个部分都可以独立于其他部分进行操作。本文将从以下几个方面深…

【web网页制作】html+css旅游家乡河南开封主题网页制作(4页面)【附源码】

HTMLCSS家乡河南主题网页目录 🍔涉及知识🥤写在前面🍧一、网页主题🌳二、页面效果Page1 首页Page2 开封游玩Page 3 开封美食Page4 留言 🌈 三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书 🐋四…

程序员副业创富:业余时间解锁首笔财富里程碑

在这个充满机遇的数字时代,我,一个普通的程序猿,编程爱好者,终于在云端源想这个平台上收获了属于我的第一桶金。这是一个关于兼职、学习与成长的故事,希望能激发同在编程路上的你,勇敢迈出那一步。 先晒晒我的首笔收入:一个普通的周末,我像往常一样,泡上一杯咖啡,坐在…

(一)文本分类经典模型之CNN篇

这篇blog对NLP领域的基本任务文本分类的CNN经典模型做了梳理CNN源于计算机视觉研究,后来诸多学者将其应用于短文本分类,其基本结构如下图所示:由上图可知,基于CNN的短文本分类模型,通常包括输入层、卷积层、池化层、全连接层和输出层五部分,其中卷积层和池化层是最为关键…

抖音小店是什么?它和直播带货有什么区别和联系?一篇详解!

大家好,我是电商糖果 在网上大家都说抖音的流量大,在抖音做电商比较赚钱。 可是有很多人对抖音电商并不了解。 甚至搞不懂抖音小店是什么?它和直播带货的区别和联系也不清楚。 下面,糖果就来给大家好好解答一下这个问题。 抖音…

Django 4.x 智能分页get_elided_page_range

Django智能分页 分页效果 第1页的效果 第10页的效果 带输入框的效果 主要函数 # 参数解释 # number: 当前页码,默认:1 # on_each_side:当前页码前后显示几页,默认:3 # on_ends:首尾固定显示几页&#…

Apache DolphinScheduler 3.3.0 版本重磅更新提前看!

Apache DolphinScheduler 3.3.0版本终于要在万众期待中发布啦!本次发版将有重大功能更新,包括架构上的调整。 为了让广大用户提前尝鲜,社区特别准备了直播活动提前揭秘3.3.0版本中的重要更新,到时候你将会了解到这些信息:3.3.0版本的工作流引擎改进 任务执行流程的优化 架…

激光雕刻优化:利用RLE压缩技术提高雕刻效率与节省能源成本

什么是 RLE ?RLE 在激光雕刻应用实现代码:总结 什么是 RLE ? RLE 是 Run-Length Encoding(游程长度编码)的缩写。这是一种数据压缩技术,它通过减少连续重复的数据来减小文件的大小。RLE 在图像处理、无损…

【重塑世界的火种】制造业:从匠人之心到智能未来之旅

在人类文明的宏伟乐章中,有一段旋律始终激昂,它既古老又现代,既是力量的象征,也是智慧的结晶——这就是制造业,一个将梦想变为现实,将创意铸就为生活的神奇领域。今天,让我们一起走进这个塑造世…

【触想智能】工业级平板电脑五大特征与应用领域分析

工业级平板电脑是专供工业环境使用的工业控制计算机,也被称为工控一体机。工业级平板电脑基本性能及兼容性与商用平板电脑几乎相同,但是工业级平板电脑更注重在不同环境下的稳定性能,因此,工业级平板电脑与普通的商用平板电脑存在一定的区别。一、工业级平板电脑的五大特征…

2024软件测试自动化面试题(含答案)

1.如何把自动化测试在公司中实施并推广起来的? 选择长期的有稳定模块的项目 项目组调研选择自动化工具并开会演示demo案例,我们主要是演示selenium和robot framework两种。 搭建自动化测试框架,在项目中逐步开展自动化。 把该项目的自动化…