
◆ 博主名称: 小此方-CSDN博客
大家好,欢迎来到小此方的博客。
⭐️Linux系列个人专栏:
【主题曲】Linux
⭐️此方的GitHub:
github_此方
⭐️
Re系列专栏:我们思考 (Rethink) · 我们重建 (Rebuild) · 我们记录 (Record)
文章目录
- 概要&序論
- 一、线程的优点
-
- 1.1线程相对于进程的优势
- 1.2 线程切换的效率有巨大优势
-
- 1.2.1线程切换不用变更进程上下文
- 1.2.2线程切换不会扰乱处理器缓存(主要原因)
- 1.2.3什么是 CPU Cache(高速缓存)
- 1.3计算密集型应用与I/O密集型应用
-
- 1.3.1计算密集型应用
- 1.3.2 I/O密集型应用
- 二、线程的缺点
-
- 2.1性能损失
- 2.2健壮性降低且编程难度提高
- 2.3缺乏访问控制(也是优点,线程天然支持共享)
- 三、线程异常
- 四、Linux进程VS线程–哪些资源共享,哪些独占
-
- 4.1进程和线程
- 4.2进程的多个线程共享
概要&序論
Hello大家好,我是此方,今天依旧是讲解线程的概念部分,这块儿理论确属蛮多的。本文将继续深入理解总结线程的优缺点,异常,资源的共享与独占各有哪些等等内容。好的,我们开始吧。
一、线程的优点
1.1线程相对于进程的优势
- 线程占用的资源要比进程少。(线程调度的时间片从进程的时间片划分)
- 线程本来就是进程的一部分,进程的优点就是线程的优点,这里不过多赘述。
- 能充分利用多处理器的可并行数量。
- 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务。
- 创建一个新的线程的代价要比创建一个新进程小得多。(因为资源已经申请好了,我们创建线程只需要创建PCB并且划分资源。)
1.2 线程切换的效率有巨大优势
与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多。
1.2.1线程切换不用变更进程上下文
最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。

我们在进程切换的时候,就是操作系统将这个current指针指向根据大O(1)调度算法调度出来的那个进程。我们的CPU找到当前进程也是通过这个指针。 这个指针往往会被优化到CPU内部的寄存器当中,于是它前面有一个建议关键字register。
1.2.2线程切换不会扰乱处理器缓存(主要原因)
另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓存 TLB (快表)会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题,当然还有硬件cache。
线程切换也会对缓存有影响,不过不会产生大面积的失效。
1.2.3什么是 CPU Cache(高速缓存)
这个东西是对用户透明的——人话就是你感知不到。
- 定义:位于 CPU 与内存之间的高速存储器,专门用于暂存 CPU 频繁访问的数据和指令。
- 作用:CPU 的处理速度远快于内存访问速度。Cache 充当缓冲垫,大幅缩短 CPU 等待数据的时间。 (CPU读取数据首先去这个缓存区尝试命中。1. 命中成功:读取数据。2. 命中失败:去读取内存。并按照局部性原理读取数据附近的数据并覆盖cache缓存区。)
- 这个chche缓存区和页表毫无关系!

1.3计算密集型应用与I/O密集型应用
1.3.1计算密集型应用
计算密集型应用(游戏画面计算,大模型计算),为了能在多处理器系统上运行,将计算分解到多个线程中实现 比如我们要计算4GB的数据进行排序,可以把它分成4份,每一份1GB让一个,进程进行排序。最后再多路归并排序 对于计算密集型应用,线程的个数==CPU个数时效率最高。 当线程创建的个数太多,反而效率下降,只有一个CPU的机器,一个线程在跑,7个线程在围观,跑完了换另外一个线程上来。这样还不如让一个线程直接一跑到底。

1.3.2 I/O密集型应用
I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。 一个进程去下载游戏资源,它不是去串行的下载。而是分成多条线程,比如有40GB的游戏资源,它会分成4条线程下载,线程一:负责0-10GB的内容下载。线程二:以此类推。于是进行I/O等待不再是一个进程串行等待,而是一排线程在等待效率翻倍。 对于I/O密集型的应用。线程个数比CPU个数稍微大一点可以提升效率,因为在IO的时候线程在等待,线程等待的时候可以有别的线程插进来先执行,可以弥补运行间隙提升效率。
总结线程的优点,关键只有一点——线程更加轻量化。(在面试的时候,如果HR问得不是太深,这么答,问题不大)。
二、线程的缺点
2.1性能损失
一个很少被外部事件阻塞的计算密集型线程往往无法与其它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。
2.2健壮性降低且编程难度提高
编写与调试一个多线程程序比单线程程序困难得多,编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
2.3缺乏访问控制(也是优点,线程天然支持共享)
进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性很大的。不同线程的代码去访问同一块内存,前者修改后影响后者的运行,一个线程引发致命错误会导致整个进程崩溃。
三、线程异常
单个线程如果出现除零,野指针问题导致线程崩溃,会干掉整个进程。 线程是进程的执行分支,线程出异常,就类似进程出异常,进而触发信号机制,终止进程,进程终止,该进程内的所有线程也就随即退出。
四、Linux进程VS线程–哪些资源共享,哪些独占
进程间具有独立性 。线程共享地址空间,也就是共享进程资源。
4.1进程和线程
进程是资源分配的基本单位,线程是调度的基本单位
线程共享进程数据,但也拥有自己的一部分"私有"数据:
- 线程ID
- 一组寄存器,线程的上下文数据(线程被独立调度)(面试这两点必须答道)
- 独立的栈结构(面试这两点必须答道)
- errno
- 信号屏蔽字
- 调度优先级
4.2进程的多个线程共享
同一地址空间,因此 Text Segment 、 Data Segment 都是共享的, 如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:
- 文件描述符表
- 每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)
- 当前工作目录
- 用户id和组id
进程和线程的关系如下图:

好的本期内容就到这里,如果对你有帮助,还不要忘记点赞三联支持。我是此方,我们下期再见。bye! Linux、C++、算法持续连载中,欢迎关注WeChat Official Account 【此方的技术栈】。






