当前位置: 首页 > news >正文

【Linux系统】线程:线程的优点 / 缺点 / 超线程技术 / 异常 / 用途




在这里插入图片描述



1、线程的优点


创建和删除线程代价较小


创建一个新线程的代价要比创建一个新进程小得多,删除代价也小。这种说法主要基于以下几个方面:

(1)资源共享

  • 内存空间:每个进程都有自己独立的内存空间,包括代码段、数据段和堆栈等。当创建一个新的进程时,操作系统需要分配新的内存空间,并复制父进程的内存内容(这被称为地址空间复制)。而线程是进程内的执行单元,所有同属一个进程的线程共享该进程的内存空间,因此创建线程时不需要进行地址空间的复制。

  • 系统资源:进程间不共享文件描述符、信号处理等系统资源,每个新进程都需要重新初始化这些资源。相比之下,同一进程内的多个线程可以共享文件描述符、信号处理器等资源。


(2)上下文切换

  • 创建新进程涉及到完整的上下文环境设置,包括用户态和内核态的各种数据结构的初始化。而创建线程时,由于大多数资源都是共享的,只需要建立线程控制块(TCB)以及分配栈空间等少量操作即可,因此上下文切换的成本更低。


(3)性能开销

  • 时间消耗:创建和销毁进程涉及大量的系统调用和内存操作,这通常需要更多的时间。线程由于减少了大量重复资源的分配与初始化工作,所以创建和销毁的速度更快,时间消耗更少。

  • 内存消耗:新进程需要分配单独的内存空间,导致内存占用相对较高;而新线程仅需分配栈空间(通常是几MB),因此内存消耗远小于创建新进程所需的消耗。




线程切换 vs 进程切换:线程切换代价较小


更加具体和详细的整理讲解可以看这篇博客:

【Linux系统】线程切换 vs 进程切换 :线程切换成本较低-CSDN博客


与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多。

最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。

(例如 CR3 寄存器存储页表的物理地址,线程切换不更换页表,则像 CR3 这类“共享的寄存器上下文就无需切换”)

另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲 TLB(快表)会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题,当然还有硬件 Cache。

意思是:多线程因为同属于同一个进程,线程之间可能会使用共享的数据或代码,因此 TLB 和 Cache 的缓存对其他线程也有帮助,而进程切换就一定要切换 TLB 和Cache 了,因为代码完全变了。



线程占用的资源要比进程少很多


同一进程内的所有线程共享该进程的大部分资源,包括内存地址空间、文件描述符、数据段等。

每个线程仅需要维护自己独立的线程控制块(TCB),这其中包括了线程的栈指针、程序计数器、寄存器集合等少量信息,因此线程占用的资源较少,切换速度也更快。

而进程之间的资源占用则多得多。每个进程都有自己的地址空间、文件描述符表、页表等,这些资源都是独立且私有的。这意味着进程之间的切换和通信开销更大,因为操作系统需要为每个进程分配独立的内存空间,并确保进程间的数据隔离与保护。



能充分利用多处理器的可并行数量。

每个处理器(这里考了单核处理器的情况)可调用一个线程,在多处理器系统下,本系统就可以同时调用多个线程,实现并行处理任务



其他优点


(1)在等待慢速 I/O 操作结束的同时,程序可执行其他的计算任务。

这个比较容易理解,例如有一个进程用于读取磁盘内容,磁盘 IO 属于慢速 IO,需要磁盘 IO 时,本进程可以创建一个线程专门用于磁盘 IO,可以创建其他线程用于其他工作任务,增加并行量,提升工作效率



(2)计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现。

例如某计算密集型应用创建一个进程用于密集型计算,需要计算十万条数据,就可以创建10个线程分别计算一万条数据,在多处理器系统上,每个处理器一次调用一个线程,这样就能在多处理器系统上将计算分解到多个线程中



(3)I/O 密集型应用,为了提高性能,将 I/O 操作重叠。线程可以同时等待不同的 I/O 操作。

这种也一样,将 IO 任务分配给多个线程处理



问题:计算密集型应用,线程是否越多越好?

答:并不是,若线程过多,则问题就由计算问题,转变为调度问题,增加了其他线程的等待时间,同时线程之间的TCB切换等工作也会耗时



问题:计算密集型应用,那线程一般建议创建多少个?

答:CPU物理个数乘于核数,相当于在多个多核处理器系统上,能够将所有CPU核心都刚好运用上



理想情况:线程数 = CPU核心数

理论基础:在理想的计算密集型应用中,每个线程都应该绑定到一个独立的CPU核心上,以避免上下文切换和资源竞争。因此,线程的数量应等于系统中的物理核心数(或逻辑核心数,如果启用了超线程技术)。

公式:

单个处理器:线程数 = 物理核心数

多核处理器:线程数 = 物理核心数 × 处理器数量

超线程技术:如果启用了超线程(Hyper-Threading),则线程数 = 逻辑核心数 = 物理核心数 × 2

示例:
如果你有一个4核的处理器,且没有启用超线程,那么理论上你应该创建4个线程。
如果你有一个8核的处理器,并且启用了超线程,那么你应该创建16个线程(8核 × 2)。



问题:什么是超线程技术?


超线程技术,每个物理核心可以模拟出两个逻辑核心。理论上,你可以创建两倍于物理核心数的线程。

超线程技术(Hyper-Threading Technology, HTT) 是英特尔(Intel)开发的一种并行计算技术,旨在通过让每个物理CPU核心模拟出多个逻辑核心(通常为两个),从而提高多线程应用程序的性能。超线程技术的核心思想是利用单个物理核心中的闲置资源来同时执行多个线程,从而提高系统的整体效率。

  • 物理核心 vs. 逻辑核心
    • 物理核心:每个物理核心是一个独立的处理单元,具备自己的算术逻辑单元(ALU)、寄存器、缓存等资源。
    • 逻辑核心:在启用超线程的情况下,每个物理核心可以模拟出两个或更多的逻辑核心。操作系统会将这些逻辑核心视为独立的处理器,并可以为每个逻辑核心分配不同的线程。
  • 资源共享
    • 在超线程技术中,物理核心的某些资源(如执行单元、缓存、浮点运算单元等)是共享的,而其他资源(如寄存器、指令队列等)则是为每个逻辑核心独立分配的。
    • 这意味着,虽然每个逻辑核心可以独立执行线程,但它们仍然共享同一物理核心的大部分硬件资源。因此,超线程并不能真正增加物理核心的数量,而是通过更高效地利用现有的资源来提高性能。

这就是为什么我的笔记本电脑有8个内核,却有16个逻辑处理器的原因



拓展:多核处理器与多处理器系统


处理器等同于CPU吗?

在广义定义上,处理器是一个更为广泛的概念,指的是任何能够执行指令并处理数据的电子设备或组件。它不仅包括中央处理器(CPU),还可以指其他类型的处理器,如图形处理器(GPU,专门用于图形渲染和并行计算)、张量处理单元(TPU,专为机器学习任务设计的处理器)等。



多核处理器与CPU的关系

  • 多核处理器:指在一个物理芯片上集成了多个CPU核心。每个核心都可以独立执行程序指令,相当于一个单独的CPU。因此,可以将多核处理器视为多个CPU核心集成在一起的处理器。
  • CPU核心:每个CPU核心都是一个完整的计算单元,能够进行指令解码、执行运算以及访问内存等操作。


多核处理器和多处理器系统的区别

  • 多核处理器

    • 在一个物理芯片上集成多个独立的CPU核心。
    • 所有核心共享同一块物理芯片上的资源,例如内存控制器、总线等。
  • 多处理器系统

    • 指一台计算机中安装了两个或更多的物理处理器(CPU芯片)。这些处理器可以是单核或多核的。
    • 每个处理器(无论是单核还是多核)都有自己的缓存、内存控制器等资源,并且它们之间需要有效的通信机制来协调工作。



2、线程的缺点

  • 性能损失
    • 一个很少被外部事件阻塞的计算密集型线程往往无法与其它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。
  • 健壮性降低
    • 编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
  • 缺乏访问控制
    • 进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。
  • 编程难度提高
    • 编写与调试一个多线程程序比单线程程序困难得多。这个主要是因为线程共享资源,容易起冲突,就需要程序员设置各种保护机制。


3、线程异常


(1)进程级别的致命信号触发

  • 当一个线程因非法操作(如访问无效内存地址)导致触发致命信号(例如SIGSEGV),这会导致整个进程终止。这是因为大多数操作系统将这类信号视为进程级别的事件,而不是单独针对产生问题的线程。因此,一旦某个线程引发这种类型的崩溃,该进程下的所有线程都会被终止。

(2)未处理的算术和内存错误导致进程崩溃

  • 如果单个线程执行了除零操作或使用了野指针,且这些行为未被捕获处理,则会引发运行时错误。在C/C++等语言中,这种情况通常会导致程序直接崩溃。如果此线程所在的进程没有设置适当的信号处理器来处理此类异常情况,那么该进程将会终止,同时其所有的线程也会随之结束。

(3)异常处理与信号机制

  • 线程作为进程的执行分支,在出现异常时首先会在其自身的上下文中尝试处理。然而,对于一些无法恢复的严重错误(比如访问非法内存地址、除零等),如果没有有效的异常处理机制,会触发相应的信号(例如SIGFPE用于算术异常,SIGSEGV用于无效内存访问)。由于这些信号默认是发送给整个进程的,而非特定线程,因此会导致整个进程终止,包括其中的所有线程。

(4)注意事项

有人说:“一个线程崩溃,其他同进程下的所有线程都会被干掉,系统会给这些线程都发相同信号。”

这句话实际上包含了几个误解点:

错误点一:一个线程崩溃,其他同进程下的所有线程都会被干掉

纠正说明:

  • 当一个线程因执行非法操作(例如访问无效内存地址或除零)导致崩溃时,并不是直接导致其他线程被“干掉”。真正发生的是该线程触发了一个致命信号(如SIGSEGV)。由于大多数操作系统将此类信号视为进程级别的事件,这意味着一旦某个线程引发了这种类型的错误,整个进程可能会因此终止。而当进程终止时,属于该进程的所有线程也会随之结束。

错误点二:系统会给这些线程都发相同信号

纠正说明:

  • 实际上,在遇到上述情况时,信号是发送给整个进程的,而不是单独发送给每个线程。在Unix/Linux等操作系统中,许多关键信号(如SIGSEGV, SIGFPE)是针对整个进程的。如果一个线程触发了这样的信号且未被捕获处理,则该信号会导致整个进程终止,而非仅仅影响到产生问题的那个线程。换句话说,没有所谓的系统直接向其他线程发送相同的信号来“干掉”它们,而是进程的终止间接导致了所有线程的结束。


(5)系统如何干掉同进程下的所有线程?

是按照线程组为单位杀死线程的。

在进程里存在线程组的概念,线程组中包含了本进程下的所有线程,而线程组的ID值为TGID。主线程(也就是第一个启动的线程)的TID等于该线程组的TGID。当某个线程触发某些异常情况导致系统发送致命信号给此进程时,在进程退出前,系统会以线程组为单位,将属于该进程的所有线程一并清除并退出。这样做确保了整个进程要么完全运行,要么彻底停止,有效地避免了由于部分线程残留可能引发的问题。



(6)有没有发送给线程的信号

确实存在可以发送给线程的信号,但这种情况与发送给进程的信号有所不同。在Unix/Linux系统中,信号通常被设计为发送给整个进程。然而,随着多线程编程的发展,也引入了对特定线程发送信号的能力。

发送给线程的信号

  • pthread_kill() 函数:在支持POSIX线程(pthreads)的系统中,可以使用pthread_kill()函数向特定的线程发送信号。这允许程序对特定线程进行更加精细的控制。例如,可以通过这种方式来中断一个长时间运行的线程而不影响整个进程。

  • 线程特定信号处理:当信号发送到特定线程时,只有目标线程会调用其注册的信号处理程序。这意味着可以在不影响其他线程的情况下单独处理某个线程中的异常情况或其他需要关注的状态变化。

综上所述,虽然大多数情况下讨论的信号都是以进程为中心的,但在多线程环境中,确实也有直接发送给特定线程的信号,并且这种机制提供了更细粒度的控制能力。



4、线程用途

  • 合理的使用多线程,能提高CPU密集型程序的执行效率
  • 合理的使用多线程,能提高IO密集型程序的用户体验(如生活中我们一边写代码一边下载开发工具,就是多线程运行的一种表现)

相关文章:

【Linux系统】线程:线程的优点 / 缺点 / 超线程技术 / 异常 / 用途

1、线程的优点 创建和删除线程代价较小 创建一个新线程的代价要比创建一个新进程小得多,删除代价也小。这种说法主要基于以下几个方面: (1)资源共享 内存空间:每个进程都有自己独立的内存空间,包括代码段…...

3.攻防世界 weak_auth

题目描述提示 是一个登录界面,需要密码登录 进入题目页面如下 弱口令密码爆破 用1 or 1 #试试 提示用admin登录 则尝试 用户名admin密码:123456 直接得到flag 常用弱口令密码(可复制) 用户名 admin admin-- admin or -- admin…...

代码随想录算法训练营| 二叉树总结

代码随想录 二叉树的理论基础:二叉树种类、存储方式、遍历方式、定义方式 二叉树遍历:深度优先和广度优先 二叉树属性:对称、深度、节点、平衡、路径、回溯 修改与构造:反转、构造、合并 涉及到二叉树的构造,无论普…...

Python OCR工具pytesseract识别数字验证码

直接下载地址:https://digi.bib.uni-mannheim.de/tesseract/ 找的最新版本: 我添加了math 跟chinese(因为是国内网络的原因吧,下载都失败,所以不用选择,后面自己下载后,添加到相应目录就好&…...

SpringBoot开发(五)SpringBoot接收请求参数

1. SpringBoot接收请求参数 1.1. 获取参数的方式 (1)通过request对象获取参数   (2)RequestParam(针对请求头方式为x-www-form-ur lencoded)   (3)RequestBody(针对请求头方式为application/json)   …...

文件基础IO

理解"文件" 1-1 狭义理解 文件在磁盘里磁盘是永久性存储介质,因此文件在磁盘上的存储是永久性的磁盘是外设(即是输出设备也是输入设备)磁盘上的文件 本质是对文件的所有操作,都是对外设的输入和输出简称IO 1-2 广义理…...

05vue3实战-----配置项目代码规范

05vue3实战-----配置项目代码规范 1.集成editorconfig配置2.使用prettier工具2.1安装prettier2.2配置.prettierrc文件:2.3创建.prettierignore忽略文件2.4VSCode需要安装prettier的插件2.5VSCod中的配置2.6测试prettier是否生效 3.使用ESLint检测3.1VSCode需要安装E…...

八大排序算法细讲

目录 排序 概念 运用 常见排序算法 插入排序 直接插入排序 思想: 步骤(排升序): 代码部分: 时间复杂度: 希尔排序 思路 步骤 gap的取法 代码部分: 时间复杂度: 选择排序 直接选…...

网络爬虫学习:借助DeepSeek完善爬虫软件,增加停止任务功能

一、引言 我从24年11月份开始学习网络爬虫应用开发,经过2个来月的努力,终于完成了开发一款网络爬虫软件的学习目标。这几天对本次学习及应用开发进行一下回顾总结。前面已经发布了两篇日志: 网络爬虫学习:应用selenium从搜*狐搜…...

docker安装es及分词器ik

系统是macos,docker是docker-desktop 拉取镜像 docker pull bitnami/elasticsearch 启动docker镜像 docker create -e "discovery.typesingle-node" \ --name elasticsearch1 -p 9200:9200 -p 9300:9300 \ bitnami/elasticsearch:8.17.1 测试是否好…...

【论文阅读】On the Security of “VOSA“

On the Security of Verifiable and Oblivious Secure Aggregation for Privacy-Preserving Federated Learning -- 关于隐私保护联邦中可验证与遗忘的安全聚合的安全性 论文来源摘要Introduction回顾 VOSA 方案对VOSA不可伪造性的攻击对于类型 I 的攻击对于类型 II 的攻击 论文…...

Docker 国内最新可用镜像源20250205

2年没用dockerhub了结果今天发现镜像无法拉取了,找了很多镜像都无效,连阿里云镜像都不行了,最后找到下面可以用的。 Docker镜像仓库备注hub.urlsa.us.kg可用http://hub.haod.eu.org可用http://hub.chxza.eu.org可用http://ccoc.eu.org部分地…...

(2025|ICLR,音频 LLM,蒸馏/ALLD,跨模态学习,语音质量评估,MOS)音频 LLM 可作为描述性语音质量评估器

Audio Large Language Models Can Be Descriptive Speech Quality Evaluators 目录 1. 概述 2. 研究背景与动机 3. 方法 3.1 语音质量评估数据集 3.2 ALLD 对齐策略 4. 实验结果分析 4.1 MOS 评分预测(数值评估) 4.2 迁移能力(在不同…...

使用 CSS 实现透明效果

在 CSS 中,实现透明效果有几种方法,具体使用哪种方法取决于具体需求。以下是一些常见的方法: 使用 opacity 属性: opacity 属性可以设置整个元素的透明度,包括其所有的子元素。 .transparent { opacity: 0.5; /* 0 表…...

4G核心网的演变与创新:从传统到虚拟化的跨越

4G核心网 随着移动通信技术的不断发展,4G核心网已经经历了从传统的硬件密集型架构到现代化、虚拟化网络架构的重大转型。这一演变不仅提升了网络的灵活性和可扩展性,也为未来的5G、物联网(LOT)和边缘计算等技术的发展奠定了基础。…...

数据库系统概论的第六版与第五版的区别,附pdf

我用夸克网盘分享了「数据库系统概论第五六版资源」,点击链接即可保存。 链接:https://pan.quark.cn/s/21a278378dee 第6版教材修订的主要内容 为了保持科学性、先进性和实用性,在第5版教材基础上对全书内容进行了修改、更新和充实。 在科…...

uniapp小程序自定义中间凸起样式底部tabbar

我自己写的自定义的tabbar效果图 废话少说咱们直接上代码,一步一步来 第一步: 找到根目录下的 pages.json 文件,在 tabBar 中把 custom 设置为 true,默认值是 false。list 中设置自定义的相关信息, pagePath&#x…...

自己实现的一个缓存数据库(搞着玩) .net Core/6/8/9

自己实现的一个缓存数据库(搞着玩) 想法来源特点说明 上代码主体基类测试类 注 想法来源 做过一个小型项目,客户要求易移植,不能使用收费的数据库,最好是一个包搞定,尝试过用sqlite,在部分linux…...

在Qt中,slots 关键字有什么用?

有下面的Qt代码&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr…...

如何查看linux机器有几个cpu

在 Linux 机器上&#xff0c;你可以使用以下几种方法来查看 CPU 的数量&#xff08;物理 CPU 和逻辑 CPU&#xff09;&#xff1a; 方法 1&#xff1a;使用 lscpu 命令 lscpu输出示例&#xff1a; CPU(s): 8 Thread(s) per core: 2 Core(s) per socket: 4 Soc…...

2024 CKA题库+详尽解析| 15、备份还原Etcd

目录 免费获取题库配套 CKA_v1.31_模拟系统 15、 备份还原Etcd 题目&#xff1a; 开始操作: 1&#xff09;、切换集群 2&#xff09;、登录master并提权 3&#xff09;、备份Etcd现有数据 4&#xff09;、验证备份数据快照 5&#xff09;、查看节点和Pod状态 6&am…...

永磁同步电机无速度算法--自适应龙贝格观测器

一、原理介绍 传统龙伯格观测器&#xff0c;在设计观测器反馈增益矩阵K时&#xff0c;为简化分析与设计&#xff0c;根据静止两相坐标系下的对称关系&#xff0c;只引入了K、K,两个常系数&#xff0c;且在实际应用时&#xff0c;大多是通过试凑找到一组合适的反馈增益系数缺乏…...

ubuntu中使用docker

上一篇我已经下载了一个ubuntu:20.04的镜像&#xff1b; 1. 查看所有镜像 sudo docker images 2. 基于本地存在的ubuntu:20.04镜像创建一个容器&#xff0c;容器的名为cppubuntu-1。创建的时候就会启动容器。 sudo docker run -itd --name cppubuntu-1 ubuntu:20.04 结果出…...

基于功能基团的3D分子生成扩散模型 - D3FG 评测

D3FG 是一个在口袋中基于功能团的3D分子生成扩散模型。与通常分子生成模型直接生成分子坐标和原子类型不同&#xff0c;D3FG 将分子分解为两类组成部分&#xff1a;官能团和连接体&#xff0c;然后使用扩散生成模型学习这些组成部分的类型和几何分布。 一、背景介绍 D3FG 来源…...

如何用AI高效运营1000+Tiktok矩阵账号

在当今数字化的时代&#xff0c;Tiktok 矩阵账号运营成为了众多企业和个人追求流量与变现的重要手段。然而&#xff0c;面对众多的账号管理&#xff0c;如何高效运营成为了关键。此时&#xff0c;AI 工具的出现为我们提供了强有力的支持。 一、Tiktok 矩阵账号的重要性 Tiktok…...

springCloud2025+springBoot3.5.0+Nacos集成redis从nacos拉配置起服务

文章目录 前言一、网关gateway选型1. 响应式编程模型2. 网关的特定需求3. 技术栈一致性4. 性能对比5. 实际应用场景优势 二、redis的集成1.引入库2.配置类A、自定义配置类RedisAfterNacosAutoConfigurationB、自定义配置类RedisConfig 总结 前言 最近在搭建最新的springCloud …...

【Android基础回顾】五:AMS(Activity Manager Service)

Android 的 AMS&#xff08;Activity Manager Service&#xff09;是 Android 系统中的核心服务之一&#xff0c;负责管理整个应用生命周期、任务栈、进程和四大组件&#xff08;Activity、Service、BroadcastReceiver、ContentProvider&#xff09;的运行。它运行在系统进程 s…...

Go 语言实现高性能 EventBus 事件总线系统(含网络通信、微服务、并发异步实战)

前言 在现代微服务与事件驱动架构&#xff08;EDA&#xff09;中&#xff0c;事件总线&#xff08;EventBus&#xff09; 是实现模块解耦与系统异步处理的关键机制。 本文将以 Go 语言为基础&#xff0c;从零构建一个高性能、可扩展的事件总线系统&#xff0c;深入讲解&#…...

GaLore:基于梯度低秩投影的大语言模型高效训练方法详解一

&#x1f4d8; GaLore&#xff1a;基于梯度低秩投影的大语言模型高效训练方法详解 一、论文背景与动机 随着大语言模型&#xff08;LLM&#xff09;参数规模的不断增长&#xff0c;例如 GPT-3&#xff08;175B&#xff09;、LLaMA&#xff08;65B&#xff09;、Qwen&#xff…...

矩阵QR分解

1 orthonormal 向量与 Orthogonal 矩阵 orthonormal 向量定义为 &#xff0c;任意向量 相互垂直&#xff0c;且模长为1&#xff1b; 如果将 orthonormal 向量按列组织成矩阵&#xff0c;矩阵为 Orthogonal 矩阵&#xff0c;满足如下性质&#xff1a; &#xff1b; 当为方阵时&…...