CPU 和 CPU Core 有啥区别?多核 CPU?多个 CPU?单核 CPU 为何也支持多线程呢?

news/2025/1/30 22:46:08/

由于现在大多计算机都是多核CPU,多线程往往会比单线程更快,更能够提高并发,但提高并发并不意味着启动更多的线程来执行。更多的线程意味着线程创建销毁开销加大、上下文非常频繁,你的程序反而不能支持更高的TPS。

CPU 组成

CPU 全称 Central Processing Unit,中央处理器,计算机的大脑,长这个样子:

图片

CPU 通过一个插槽安装在主板上,这个插槽也叫做 CPU Socket,它长这个样子:

图片

而我们说的多核 CPU,一个 CPU 有几个核,这个核就是 Core

其实在很久之前是没有 Core 的概念的,一个 CPU 就是一个完整的物理处理单元,之后由于多核技术的发展,CPU 的概念转变为了一个容器(container),而 Core 则变成了真正的物理处理单元

一个 CPU 中可以有多个 Core,各个 Core 之间相互独立且可以并行执行

图片

所以你说一个多核 CPU 支不支持多进程/线程并行?

当然是可以的,进程具体是由 Core 来执行的,并不是说 1 个 CPU 同时只能执行 1 个进程/线程。

A core can work on one task, while another core works a different task, so the more cores a CPU has, the more efficient it is(一个核心可以执行一项任务,而另一个核心执行不同的任务,因此 CPU 拥有的核心越多,它的效率就越高)

一般来说,我们可以将一个 Core 分为三个主要部分:控制单元(Control Unit,CU)、算术逻辑单元(Arithmetic-Logic Unit,ALU)和内存(Memory)

  • 控制单元:使 Core 与计算机系统的其他组件进行通信
  • 算术逻辑单元:这个单元由执行算术和逻辑运算的电子电路组成。通常,ALU 执行四种算术运算 - 加、减、乘、除。此外,它通常执行三个逻辑操作 - 等于、小于和大于
  • 内存:内核中构建的内存由寄存器和缓存(L1 Cache 和 L2 Cache)组成。寄存器用于保存地址、指令和核心处理计算结果。缓存是高速随机访问存储器,它保存 Core 可能会(重新)使用的数据

除了这三大块,Core 中还包括时钟和总线,就不详细说了,下图显示了一个抽象的 Core 架构:

图片

那这些 Core 互相独立的执行任务,谁负责来对他们进行协调呢?

没错,CPU 上剩余的部分,也就是 UnCore 部分就是干这个事儿的:Coordinates cores for executing tasks in a computer system. (常见的比如 L3 Cache 就是在这里,一个 CPU 上的所有 Core 共享一个 L3 Cache)

图片

可以配合下面这个图片理解下,来源 https://www.intel.com/content/www/us/en/developer/articles/technical/performance-counter-monitor.html

图片

对于我们做上层 Web 开发的话,关注的应该是 CPU Core 的数量,而非 CPU 数量,比如常见的线程池的 corePoolSize 设置为 CPU 个数 * 2,这里的 CPU 个数,其实指的就是 CPU Core 的个数

当然了,还有 Hyper-threading 超线程这种技术,在 Core 的基础上再做扩展,将一个 Core 分裂成多个虚拟核心 Virtual Core

超线程

现代 CPU 除了处理器核心之外还包括寄存器、L1、L2 缓存这些存储设备、浮点运算单元、整数运算单元等一些辅助运算设备以及内部总线等。一个多核的 CPU 也就是一个 CPU 上有多个处理器核心,就意味着程序的不同线程需要经常在 CPU 之间的外部总线上通信,同时还要处理不同 CPU 之间不同缓存导致数据不一致的问题。

超线程这个概念是 Intel 提出的,简单来说是在一个 CPU 上真正的并发两个线程,由于 CPU 都是分时的(如果两个线程 A 和 B,A 正在使用处理器核心,B 正在使用缓存或者其他设备,那 AB 两个线程就可以并发执行,但是如果 AB 都在访问同一个设备,那就只能等前一个线程执行完后一个线程才能执行)。实现这种并发的原理是 在 CPU 里加了一个协调辅助核心,根据 Intel 提供的数据,这样一个设备会使得设备面积增大 5%,但是性能提高 15%~30%。

时间片

多任务系统往往需要同时执行多道作业。作业数往往大于机器的 CPU 数,然而一颗 CPU 同时只能执行一项任务,如何让用户感觉这些任务正在同时进行呢? 操作系统的设计者 巧妙地利用了时间片轮转的方式

时间片是 CPU 分配给各个任务(线程)的时间!

思考:单核 CPU 为何也支持多线程呢?

线程上下文是指某一时间点 CPU 寄存器和程序计数器的内容,CPU 通过时间片分配算法来循环执行任务(线程),因为时间片非常短,所以 CPU 通过不停地切换线程执行。

换言之,单 CPU 这么频繁,多核 CPU 一定程度上可以减少上下文切换。

上下文切换

  • 线程切换,同一进程中的两个线程之间的切换
  • 进程切换,两个进程之间的切换
  • 模式切换,在给定线程中,用户模式和内核模式的切换
  • 地址空间切换,将虚拟内存切换到物理内存

CPU 切换前把当前任务的状态保存下来,以便下次切换回这个任务时可以再次加载这个任务的状态,然后加载下一任务的状态并执行。任务的状态保存及再加载, 这段过程就叫做上下文切换。

每个线程都有一个程序计数器(记录要执行的下一条指令),一组寄存器(保存当前线程的工作变量),堆栈(记录执行历史,其中每一帧保存了一个已经调用但未返回的过程)。

寄存器 是 CPU 内部的数量较少但是速度很快的内存(与之对应的是 CPU 外部相对较慢的 RAM 主内存)。寄存器通过对常用值(通常是运算的中间值)的快速访问来提高计算机程序运行的速度。

程序计数器是一个专用的寄存器,用于表明指令序列中 CPU 正在执行的位置,存的值为正在执行的指令的位置或者下一个将要被执行的指令的位置。

  1. 挂起当前任务(线程 / 进程),将这个任务在 CPU 中的状态(上下文)存储于内存中的某处
  2. 恢复一个任务(线程 / 进程),在内存中检索下一个任务的上下文并将其在 CPU 的寄存器中恢复
  3. 跳转到程序计数器所指向的位置(即跳转到任务被中断时的代码行),以恢复该进程在程序中

img

线程上下文切换会有什么问题呢?

上下文切换会导致额外的开销,常常表现为高并发执行时速度可能会慢于串行,因此减少上下文切换次数便可以提高多线程程序的运行效率。

  • 直接消耗:指的是 CPU 寄存器需要保存和加载, 系统调度器的代码需要执行, TLB 实例需要重新加载, CPU 的 pipeline 需要刷掉
  • 间接消耗:指的是多核的 cache 之间得共享数据, 间接消耗对于程序的影响要看线程工作区操作数据的大小

切换查看

Linux 系统下可以使用 vmstat 命令来查看上下文切换的次数, 其中 cs 列就是指上下文切换的数目**(一般情况下, 空闲系统的上下文切换每秒大概在 1500 以下)**

img

线程调度

抢占式调度

指的是每条线程执行的时间、线程的切换都由系统控制,系统控制指的是在系统某种运行机制下,可能每条线程都分同样的执行时间片,也可能是某些线程执行的时间片较长,甚至某些线程得不到执行的时间片。在这种机制下,一个线程的堵塞不会导致整个进程堵塞。

java 使用的线程调使用抢占式调度,Java 中线程会按优先级分配 CPU 时间片运行,且优先级越高越优先执行,但优先级高并不代表能独自占用执行时间片,可能是优先级高得到越多的执行时间片,反之,优先级低的分到的执行时间少但不会分配不到执行时间。

img

协同式调度

指某一线程执行完后主动通知系统切换到另一线程上执行,这种模式就像接力赛一样,一个人跑完自己的路程就把接力棒交接给下一个人,下个人继续往下跑。线程的执行时间由线程本身控制,线程切换可以预知,不存在多线程同步问题,但它有一个致命弱点:如果一个线程编写有问题,运行到一半就一直堵塞,那么可能导致整个系统崩溃。

img

线程让出 cpu 的情况

  • 当前运行线程主动放弃 CPU,JVM 暂时放弃 CPU 操作(基于时间片轮转调度的 JVM 操作系统不会让线程永久放弃 CPU,或者说放弃本次时间片的执行权),例如调用 yield() 方法。
  • 当前运行线程因为某些原因进入阻塞状态,例如阻塞在 I/O 上
  • 当前运行线程结束,即运行完 run() 方法里面的任务

引起线程上下文切换的因素

  • 当前执行任务(线程)的时间片用完之后,系统 CPU 正常调度下一个任务
  • 中断处理,在中断处理中,其他程序” 打断” 了当前正在运行的程序。当 CPU 接收到中断请求时,会在正在运行的程序和发起中断请求的程序之间进行一次上下文切换。中断分为硬件中断和软件中断,软件中断包括因为 IO 阻塞、未抢到资源或者用户代码等原因,线程被挂起。
  • 用户态切换,对于一些操作系统,当进行用户态切换时也会进行一次上下文切换,虽然这不是必须的。
  • 多个任务抢占锁资源,在多任务处理中,CPU 会在不同程序之间来回切换,每个程序都有相应的处理时间片,CPU 在两个时间片的间隔中进行上下文切换

因此优化手段有:

  • 无锁并发编程,多线程处理数据时,可以用一些办法来避免使用锁,如将数据的 ID 按照 Hash 取模分段,不同的线程处理不同段的数据
  • CAS 算法,Java 的 Atomic 包使用 CAS 算法来更新数据,而不需要加锁
  • 使用最少线程
  • 协程,单线程里实现多任务的调度,并在单线程里维持多个任务间的切换

合理设置线程数目既可以最大化利用 CPU,又可以减少线程切换的开销。

  • **高并发,低耗时的情况,**建议少线程。
  • 低并发,高耗时的情况:建议多线程。
  • **高并发高耗时,**要分析任务类型、增加排队、加大线程数

http://www.ppmy.cn/news/485713.html

相关文章

多线程的好处与弊端

在创建线程之前先说明一下基本概念: 串行与并行: 串行(同步):模仿人类做事,做完一件事之后做下一件事(比如穿衣服上厕所) 并行(异步): 做一件事的时候,不用等上件事情做完,就做下一件事情(比如吃饭的时候…

线程开的越多就越好吗?

作者:九心 线程优化一直是启动优化中的一个必不可少的项目。作为一个 Android 程序员,你肯定希望应用启动的时候,火力全开,线程池拉满,每一个 CPU 核心满载而行。 可你把线程池拉满的时候,启动时长就一定会…

超线程和多线程的区别

关于线程,多线程,并发,并行等操作系统的基础知识,可以回顾我之前的博客 操作系统学习之一常用术语 物理CPU: 物理CPU就是插在主机上的真实的CPU硬件,在Linux下可以数不同的physical id 来确认主机的物理CP…

多线程还是多进程的选择及区别

鱼还是熊掌:浅谈多进程多线程的选择 关于多进程和多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,线程是CPU调度的最小单位”,这句话应付考试基本上够了,但如果在工作中遇到类似的选择问题,那…

多进程和多线程区别以及优缺点

多进程和多线程主要区别是:线程是进程的子集,一个进程可能由多个线程组成。多进程的数据是分开的、共享复杂,需要用IPC,但同步简单;多线程共享进程数据、共享简单,但同步复杂。 多进程,window应…

多线程和CPU的关系

什么是CPU (1) Central Progressing Unit 中央处理器,是一块超大规模的集成电路,是一台计算机的运算核心和控制核心。 (2) CPU包括 运算器,高速缓冲存储器,总线…

多线程和cpu得关系

我看网上不少资料 当时看多线程文章的时候,看到一句话 叫 多线程下cpu也是一个一个执行的,当时一直不明白原因 后来查询好多资料 找到了 大多是转载 参考链接1 既然CPU同一时间只能执行一个线程,为什么存在并发问题 一点小疑惑终于解开啦 1…

面试中常被问到的(17)多线程及多进程优缺点

多进程: 优点: 进程资源相互独立,互不干扰,子程序崩溃不影响主程序的稳定性。进程比较稳定健壮通过增加cpu核心数,可以很容易扩充性能尽量减少线程加锁解锁的影响,极大提高性能每一个进程可以获得本地全…