【Linux】多线程:线程概念,线程与进程的区别与联系,多线程相较于多进程的优势

news2024/11/15 11:20:11

目录

一、进程基本属性回顾

二、线程概念

三、操作系统为什么要引入线程—多进程和多线程的区别 

为什么多线程比多线程调度效率更快?

 四、线程的优点

 五、线程的缺点

六、线程异常


一、进程基本属性回顾

在学习线程之前,我们先来回顾一下进程的基本属性:

1、进程是一个可拥有资源的独立单位——即进程是系统资源分配的基本单位。一个进程能够独立运行,就必须拥有一定的资源,包括:存放程序正文和数据的磁盘、内存地址空间、运行时所需要的I/O设备、进程已经打开的文件、信号量等。

2、进程是一个可独立调度和分派的基本单位。每个进程在系统中均有唯一的PCB(在Linux系统中是task_struct),系统可以根据PCB来感知进程的存在,也可以根据PCB中的信息对进程进行调度,还可将断点信息保存在进程的PCB中 。反之,也可以利用PCB中的信息来恢复进程运行的现场。

正是因为进程具有以上基本属性,进程才成为了可以独立运行的基本单位,从而也构成了进程并发执行的基础。

二、线程概念

那么什么是线程呢?我们先引入如下概念:线程是进程的一个实体,是CPU调度和分派的基本单位!

到这里可能有同学会有疑问了:之前不是说进程是是一个可独立调度和分派的基本单位吗?现在怎么又说线程是CPU调度和分派的基本单位了?

其实在已经引入线程的操作系统中,就已经把线程作为CPU调度和分派的基本单位了!

在Linux系统当中,我们可以这么来理解进程和线程:进程是操作系统进行资源分配的基本单位,线程是CPU调度和分派的基本单位!

那我们如何理解之前所学的进程呢?我们之前所学习的进程中,其实只包含一个执行流,也就是一个线程!实际上,我们之前所学习的进程是:具有一个执行流的进程,而一个进程必须至少拥有一个线程!!! 

举个更通俗的例子:在我们国家中,家庭通常是政府进行资源分配的单位,则家庭可以视为进程,而一个家庭至少包含一个家庭成员,也可包含多个,且家庭成员共享家庭的资源,但家庭成员又有各自的隐私,因此可以将家庭成员视为线程。家庭成员各自的任务和活动(如工作、学习、娱乐)可能会不同,但都在共享的家庭资源框架内进行。这类似于线程在进程中执行不同的操作,虽然每个线程可能执行不同的任务,但都在同一进程的资源和环境下运行。增加一个新的家庭成员(比如增加一个子女)相对容易,家庭的资源和管理模式不会发生重大改变。这类似于创建新线程的开销很小,因为新线程与现有线程共享资源和环境。相比之下,创建一个新的家庭(即进程)需要更多的资源和管理成本。

通过上图我们可以大致了解到:

1、在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”。

2、线程在进程内部运行,本质是在进程地址空间内运行。线程就是进程中的一个执行单元,是进程的一部分一个进程至少有一个线程(主线程)可以创建多个线程来并行执行任务

3、透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流。同一进程中的所有线程共享进程的资源,但它们的执行是独立的。线程有自己的执行路径,可以同时进行多项任务,从而实现并发。

4、进程的多个线程共享同一地址空间,因此代码段和数据段都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:文件描述符表、每种信号的处理方式、当前工作目录、用户 ID 和组 ID

【了解】:但是实际上,Linux操作系统并没直接创造“线程”这一具体的事物,而是通过创造“轻量级进程(Lightweight Process, LWP)”来实现线程的功能。

用户视角:Linux 使用 pthread(POSIX线程)库来提供线程创建和管理的接口。pthread 库为线程提供了标准化的 API,允许程序员创建和管理线程、进行线程同步等。

内核视角:在内核中,每个线程是一个进程,但具有某些共享资源。内核的调度器处理这些线程就像处理进程一样。

所以我们在Linux系统中编写程序时,我们所面对的是pthread库为我们提供的管理“线程”的方法,在内核中实际上是被当作轻量级进程(LWP)来处理的,因此我们称Linux中的线程为“用户级线程”。而在Windows操作系统中,内核为线程专门创造了TCB这一数据结构来对每个线程进行标识和管理,而这些操作都由Windows内核来进行管理,所以我们称之为内核级线程。 

所以在Linux内核看来,对线程的调度与管理实际上就是对进程的调度与管理,依然可以沿用进程调度的那一套算法。而Windows则需要单独为线程创造一套专属的数据结构与方法。

这也是为什么在 Linux 系统中:在 CPU 眼中,看到的 PCB 都要比传统的进程更加轻量化!

三、操作系统为什么要引入线程—多进程和多线程的区别 

实际上,线程的引入是为了更好的提高程序的并发程度。

在引入线程这一概念之前,程序的并发执行多由多进程进行实现。但是通过之前的学习我们知道:进程是系统资源分配的单位,当多个进程并发执行时,势必会为系统资源的分配带来压力!

使用多进程时,系统必须要进行如下操作:

1、创建进程:系统在创建一个进程时,必须为它分配其所必须的、除处理机以外的所有资源(如内存空间、I/O设备等),并创建对应的PCB。

2、撤销进程:系统在撤销进程时,必须先对其所占有的资源执行回收操作,然后再撤销PCB。

3、进程切换:对进程进行上下文切换时,需要保留当前进程的CPU环境,这一过程需要花费不少的处理机时间。

由于进程是资源的拥有者,因此在对进程进行管理时,操作系统必须付出较大的时空开销。这就限制了系统中所设置的进程的数目,而且进程的切换也不宜过于频繁,从而限制了程序并发程度的进一步提高。

因此为使多个程序能够更好的并发执行,同时又能减少系统的开销,线程就应运而生。线程的出现将进程的两个基本属性分割开来:从此进程仅作为拥有资源的基本单位,线程则成为了调度和分派的单位。因此,在使用多线程时,由于多线程共享所属进程中的资源,因此减少了资源的频繁切换。

但同时,线程也有属于自己的资源:

  1. :每个线程都有自己的独立的栈,用于存放函数调用时执行上下文的数据,如局部变量、函数参数等。栈是线程特有的,可以确保线程之间不受其他线程的影响。

  2. 一组寄存器的状态:线程执行时所使用的寄存器,例如,程序计数器、寄存器组等,每个线程都有自己的寄存器状态,这是独立于其他线程的。

  3. 线程ID:每个线程都有自己的线程标识符(Thread ID),可以在同一进程中的其他线程或同级的用户程序中进行线程间通信或同步时识别和引用。

  4. 执行上下文:线程的执行上下文包含其调用的特定状态,如寄存器状态、指令指针等。这些状态在上下文切换时被保存和恢复。

  5. 线程局部存储(TLS):线程局部存储是特定于线程的全局变量,允许每个线程拥有一个独立的副本,但此全局变量必须为内置类型,且需要在变量类型前使用__thread关键字。

  6. errno :在多线程程序中,errno 通常被实现为线程局部存储(TLS),每个线程有自己的 errno 副本,确保线程之间不会相互干扰。

  7. 信号屏蔽字:每个线程都有自己的信号屏蔽字,它决定了该线程是否响应某些信号。线程可以通过系统调用(如 sigprocmask)来设置或更改信号屏蔽字。
  8. 调度优先级:每个线程都有一个调度优先级,操作系统根据这些优先级来安排线程的运行。高优先级的线程通常会比低优先级的线程获得更多的 CPU 时间。

 如此,我们便不难回答:

为什么多线程比多线程调度效率更快?

1、共享资源:多个线程可以在同一个进程中共享资源,如堆栈、状态和数据。这意味着它们可以更快地访问同样的内存地址,减少了内存的访问时间。

2、上下文切换:线程的上下文切换通常比进程的上下文切换速度更快。因为线程共享了地址空间和大部分内核资源,所以切换线程所需的时间相比于进程要短。

3、缓存命中率:在多线程应用程序中,多个线程可以共享缓存中的数据,这可以提高缓存命中率。由于多个线程共享同样的数据,这意味着他们更有可能从高速缓存中读取数据,而不是从更慢的主存中读取。

缓存(Cache)是一种基于内存的高速数据存储技术,用于提高数据访问速度。缓存可以是硬件层面的,也可以是软件层面的。在计算机科学中,缓存主要用在CPU缓存中,即高速缓存。

4、减少系统调用:在多线程应用程序中,多个线程可以在同一个进程中共享相同的文件描述符和网络连接,这意味着它们可以重用同样的一些资源,而不是创建多个进程时必须重新打开资源。

5、减少地址空间开销:进程有它们自己的地址空间,而线程共享相同的地址空间,这意味着多个线程可以节省虚拟内存的开销。

 四、线程的优点

• 创建一个新线程的代价要比创建一个新进程小得多

• 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多 • 线程占用的资源要比进程少很多

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

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

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

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

 五、线程的缺点

• 等候使用共享资源时会使程序的运行速度变慢,这些共享资源主要是独占性的资源,如打印机等。

• 对线程进行管理要求额外的CPU开销。线程的使用会给系统带来上下文切换的额外负担,当这种负担超过一定程度时,多线程的缺点会表现得较突出,比如用独立的线程来更新数组内每个元素。

•线程的死锁。即较长时间的等待或资源竞争,以及死锁等多线程症状。

•对公有变量的同时读或写。当多个线程需要对公有变量进行写操作时,后一个线程往往会修改掉前一个线程存放的数据,从而使前一个线程的参数被修改;另外,当公用变量的读写操作是非原子性时,在不同的机器上,中断时间的不确定性会导致数据在一个线程内的操作产生错误,从而产生莫名其妙的错误,而这种错误是程序员无法预知的。

六、线程异常

  1. 线程异常与进程崩溃

    • 线程在运行过程中如果发生异常,如除零错误、访问野指针等,通常会导致线程崩溃。这些异常可能会引发操作系统层面的信号(例如 SIGFPE 对于除零错误,SIGSEGV 对于访问非法内存),这些信号会触发进程的终止机制
    • 当一个线程崩溃时,通常会导致整个进程的崩溃。这是因为线程共享进程的地址空间和资源,线程的异常可能会破坏进程的整体状态,从而导致进程无法继续安全地运行。
  2. 信号机制

    • 当线程发生致命异常时,操作系统会发送信号到进程,这些信号可能会导致进程的终止。例如,除零错误可能触发 SIGFPE,访问非法内存可能触发 SIGSEGV。这些信号会通知操作系统对进程进行处理,通常会导致整个进程的退出。
    • 在某些情况下,可以使用信号处理机制来捕获这些信号,从而进行一些清理工作或记录日志,但通常情况下,如果信号表示严重错误,进程会被终止。

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

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

相关文章

6. LinkedList与链表

一、ArrayList的缺陷 通过源码知道,ArrayList底层使用数组来存储元素,由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比…

64、Python之函数高级:装饰器实战,动态语言也能有类型检查

引言 Python作为一门动态类型语言,有时候,一个不小心的类型错误只有在实际运行中才有可能被发现。相较而言,静态类型语音虽然不够灵活,但是,类型错误等语法检查在编译期间就可以提前发现了。 那么我们有没有方法在Py…

Visual Studio Code 月刊 (2024-08)

文章目录 配置文件编辑器Django 单元测试支持vscode.dev 上的 IntelliSenseNotebook 差异查看器通过键盘调整列的大小源代码管理图GitHub Copilot结语 2024 年 8 月 Visual Studio Code(简称 vscode)发布了 version 1.93。该版本带来了许多更新&#xff…

Spring Boot Admin集成与自定义监控告警

目录 一.Spring Boot Admin集成 1.引入依赖 2.添加配置 3.监控界面 二.Spring Boot Admin告警机制 1. 基本告警机制 2. 配置告警 2.1 triggers触发器讲解 3. 自定义通知 3.1 Instance 对象 三.Spring Boot Admin支持的监控属性 1.常见的Spring Boot Admin监控属性 …

进阶SpringBoot之配置 Swagger API 框架信息

Swagger:API 框架 RestFul API 文档在线自动生成工具,API 文档与 API 定义同步更新 Swagger 官网 Maven 仓库 创建 Spring Boot 项目,依赖勾选 Spring Web pom.xml 导入相关依赖: springfox-swagger2、springfox-swagger-ui …

何为数据中台

数据中台 什么是数据中台 2014年马云正式提出“DT(Data Technology)”的概念,人类从IT时代走向了DT时代,阿里内部的数据平台事业部大刀阔斧的建立整个集团的数据资产,同年,阿里从芬兰Supercell公司接触到…

Canny算子 一张图看懂

对于最高值和最低值的设置, 1,high t最大值一般以一阶导数幅度图的最大值的30%-40%来定 2,最小值一般halcon里默认为 low theigh t/3得到 3,canny的优势是有极大值抑制,所以提取的边缘是1个像素的窄边缘。 3&#xff0…

Golang path/filepath包详解:高效路径操作与实战案例

Golang path/filepath包详解:高效路径操作与实战案例 引言基础用法Abs 函数Base 函数Clean 函数Dir 函数Ext 函数FromSlash 和 ToSlash 函数 基础用法Abs 函数Base 函数Clean 函数Dir 函数Ext 函数FromSlash 和 ToSlash 函数 路径操作Join 函数Split 函数Rel 函数Ma…

LabVIEW编程语言出于什么原因开发的?

LabVIEW最初由美国国家仪器公司(NI)于1986年开发,目的是为工程师和科学家提供一种图形化编程环境,简化数据采集、仪器控制、自动化测试和测量系统开发等工作。开发LabVIEW的主要原因包括以下几点: 简化复杂系统开发&am…

《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》Chapter 1课件2024

每一轮备课都有新的感悟。 禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》 禹晶、肖创柏、廖庆敏《数字图像处理》资源二维码

Tektronix泰克MSO5204B混合信号示波器4+16通道2G

Tektronix泰克MSO5204B混合信号示波器416通道2G 2 GHz、416 通道、10/5 GS/s(2/4 通道)混合信号示波器,50 M/25 M 记录长度泰克 MSO5204B 2 GHz、416 通道、10/5 GS/s(2/4 通道)混合信号示波器,50 M/25 M …

机器学习强化学习

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl1. 强化学习概述 1.1 定义与核心概念 强化学习是一种目标导向的机器学习方法,它使智能体能够在环境中通过试错学习最优行为策略。这种学习过程涉及到智能体与环境之间的交互,智能体根据当前状态…

AI基础 L8 Local Search I 局部搜索

Iterative Improvement Algorithms • In many optimization problems, the path to a goal is irrelevant — the goal state itself is the solution • State space a set of goal states — find one that satisfies constraints (e.g., no two classes at same time) —…

《系统安全架构设计及其应用》写作框架,软考高级系统架构设计师

论文真题 随着社会信息化进程的加快,计算机及网络已经被各行各业广泛应用,信息安全问题也变得愈来愈重要。它具有机密性、完整性、可用性、可控性和不可抵赖性等特征。信息系统的安全保障是以风险和策略为基础,在信息系统的整个生命周期中提…

【审批流】基于JAVA开发的工作流审批系统(直接集成或者直接可使用)

基于Javavue开发的智能审批系统,低代码平台 软件资料清单列表部分文档清单:工作安排任务书,可行性分析报告,立项申请审批表,产品需求规格说明书,需求调研计划,用户需求调查单,用户需…

Android APK插件化:DynamicAPK技术如何改变游戏规则

在移动应用开发领域,尤其是Android平台,应用的体积和更新速度一直是开发者和用户关注的焦点。随着应用功能的不断增加,APK文件的大小也在逐渐膨胀,这不仅增加了用户的下载成本,也影响了应用的更新效率。DynamicAPK技术…

数学建模笔记——层次分析法

数学建模笔记——层次分析法 数学建模笔记——层次分析法1. 层次分析法的基本原理和步骤2. 层次分析法的建模过程2.1 问题的提出2.2 模型原理2.3 为该问题建立层次结构模型2.4 构造判断矩阵1. 判断矩阵的含义2. 为该问题构造判断矩阵 2.5 一致性检验1. 一致性检验方法2. 对上述…

【Linux】HTTP协议中的cookie和session

一、B站的登录和未登录——一种登录场景的演示 我们现在上的是B站大学,所以对于B站,我们是很熟悉的。当我们打开浏览器,并访问B站网页时(很熟悉),会发现我们会自动登录上B站,为什么呢&#xff1…

解锁 macOS 剪贴板历史记录,高效复制、粘贴技巧

在Mac上,我们经常需要在不同文档之间复制和粘贴内容。然而,macOS自带的剪贴板只能保存最后一个复制项,这大大限制了我们的工作效率。幸运的是,一些第三方应用程序可以帮助我们查看和管理剪贴板的历史记录,从而提升我们…

基于RP2350 MCU的树莓派Pico 2开发板及MicroPython编程使用

2021年1月21日,树莓派基金会同时发布了第1代RP2040 MCU芯片和基于RP2040 MCU的第1代树莓派Pico开发板(Raspberry Pi Pico/ Raspberry Pi Pico 1)。2024年8月8日,树莓派基金会又发布了第2代RP2350 MCU芯片并推出了基于RP2350 MCU的第2代树莓派Pico开发板(Raspberry Pi Pico 2)…