由于现在大多计算机都是多核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. 跳转到程序计数器所指向的位置(即跳转到任务被中断时的代码行),以恢复该进程在程序中

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

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

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

切换查看

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

线程调度

抢占式调度

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

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

协同式调度

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

线程让出 cpu 的情况

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

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

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

因此优化手段有:

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

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

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

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

  1. cpu核数和逻辑个数的区别_CPU逻辑核心数和物理核心数是什么意思?

    展开全部 1.物理cpu数:主板上实际插入的cpu数量,可以数不重e69da5e887aa3231313335323631343130323136353331333366303666复的 physic ...

  2. Linux系统下,CPU信息详解(cpuinfo,多核,多线程)

    在 Linux 系统中,如何详细了解 CPU 的信息呢? 当然是通过cat /proc/cpuinfo来检查了,但是比如几个物理CPU/几核/几线程,这些问题怎么确定呢? 经过查看,我的开发机器是2个 ...

  3. 处理器关于多核概念与区别 多核处理器工作原理及优缺点

    +关注 摘要:目前关于处理器的单核.双核和多核已经得到了普遍的运用,今天我们主要说说关于多核处理器的一些相关概念,它的工作与那里以及优缺点而展开的分析. 1.多核处理器 多核处理器是指在一枚处理器中集 ...

  4. 单核CPU如何执行多线程

    概述 在多处理器系统中,多个线程在不同的内核上同时执行. 例如,如果有两个线程和两个内核,则每个线程将在单个内核上运行.在单处理器系统中,多个线程执行一个接一个的执行,或者等到一个线程完成或被操作系统 ...

  5. java单核cpu飙高考死_java多线程在单核CPU上,还是需要volatile synchronized吗?

    本来不想回答的,可是看了这么多答案,有的不是特别靠谱.斗胆写个粗略的回答. 首先,JMM是不区分是否JVM到底是运行在单核处理器.单核超线程处理器.多核处理器,抑或是多核超线程处理器上的.就是说,Ja ...

  6. 面试官:单核 CPU 支持 Java 多线程吗?什么?

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

  7. 单核CPU与多核CPU的区别,多线程的优点,什么是并行?并发?

    单核cpu:是一种假的多线程,因为在一段时间内只能执行一个线程的任务.但是由于cpu执行时间特别短,所以感觉不出来 多核cpu可以更好的发挥多线程的效率 一个java应用程序java.exe,其实至少 ...

  8. 单核CPU与多核CPU的区别

    1.单核CPU 1.1 工作原理 工作原理:单核CPU较为死脑,在通电时该CPU就会执行存储块中的指定地址的指令,如果你想要执行内存块其他地方的代码必须调整总线位置才可以让其执行.单核CPU就相当于阻 ...

  9. CPU怎么选择,单核cpu与多核cpu的区别

    CPU是一台计算机的运算核心和控制核心.CPU主要功能是解释计算机指令以及处理计算机软件中的数据.CPU由运算器.控制器和寄存器及实现它们之间联系的数据.控制及状态的总线构成. cpu怎么选 1.核心 ...

最新文章

  1. 人工智能助力资深内容营销人员
  2. PyTorch 0.4新版本 升级指南 no_grad
  3. 第一课-并行编程的几个概念
  4. python 处理xml pandas_Python数据处理分析,解决pandas中所有的Excel疑难杂症(上)
  5. ES6新特性之字符串扩展
  6. LiveVideoStackCon 2022 上海站 专题抢先看(4)
  7. 为WPF, UWP 及 Xamarin实现一个简单的消息组件
  8. ASP.NET Session详解
  9. 以太坊—JSON RPC API
  10. hbase 监控指标项
  11. cgi python_通读Python官方文档之cgi
  12. 科沃斯扫地机器人橡胶配件_扫地机器人主要配件,扫地机器人配件详解
  13. 查找计算机的dos,dos命令dir查找文件的用法及实例
  14. 马哥python培训学校怎么样
  15. python是一门胶水语言_Python是唯一被称为“胶水语言”的编程语言?事实并非如此!...
  16. vue中Axios的封装和API接口的管理
  17. 大屏可视化解决方案:公安大数据平台建设
  18. Android Studio记录一个错误:解析软件包时出现问题
  19. 年终奖买啥最合适?马上安排降噪耳机界的扛把子,索尼WF-1000XM4
  20. 工业场景知识图谱落地实战

热门文章

  1. SHELL脚本(文件归档)
  2. 数据仓库工程师、大数据开发工程师、BI工程师、ETL工程师之间有什么区别?...
  3. xshell中查找命令_Xshell中操作Linux的常用命令
  4. WARNING: NMS time limit 1.060s exceeded
  5. c语言中1e18怎么控制条件,C语言复习之实验五
  6. Windows10下的C盘扩容问题,亲测可用
  7. html写一个简单的浏览页面
  8. 【WPF】 InkCanvas 书写毛笔效果
  9. [健康]那到底有哪些食物吃了会让我们易长皱纹呢?
  10. 移动web资源整理[转]