关于前端:并发编程大扫盲带你了解何为线程上下文切换

6次阅读

共计 1902 个字符,预计需要花费 5 分钟才能阅读完成。

关注“Java 后端技术全栈”

回复“面试”获取全套面试材料

在并发程序中,对于线程数设置大小的说法:

线程数量设置太小,可能会导致程序不能充分利用好系统资源。

线程数量设置太大,可能会带来资源的适度竞争,导致上下文切换给零碎带来额定的开销。

何为上下文切换?

在单核 CPU 时代,操作系统其实就曾经能解决多线程并发工作了。处理器会给每个线程调配一个 CPU 工夫片,线程会在获取的工夫片内执行工作。

工夫片的概念是什么?

工夫片即 CPU 调配给各个程序的工夫,每个线程被调配一个时间段,称作它的工夫片,即该过程容许运行的工夫,使各个程序从外表上看是同时进行的。

时间段个别为几十毫秒。

如果在工夫片完结时过程还在运行,则 CPU 将被剥夺并调配给另一个过程。如果过程在工夫片完结前阻塞或完结,则 CPU 当即进行切换。而不会造成 CPU 资源节约。

宏观上:咱们能够同时关上多个应用程序,每个程序并行不悖,同时运行。当咱们开启微信、QQ、IDEA、数据库等,我基本上是感触不到处理器一直的进行工夫片切换。

宏观上:因为只有一个 CPU,一次只能处理程序要求的一部分,如何解决偏心,一种办法就是引入工夫片,每个程序轮流执行。

何为上下文切换?

当一个线程的工夫片用完后或者其余本身起因被迫暂停运行了,这时候,另外一个线程或者、过程或者其余过程的线程就会白操作系统选中,用来占用处理器。

这种一个线程被暂停,一个线程包选中开始执行的过程就叫做上下文切换。

和 CPU 寄存器、程序计数器的关系

上下文切换蕴含了寄存器的存储和程序计数器存储的指令内容。

CPU 寄存器负责存储曾经、正在和行将要执行的工作。

程序计数器负责存放 CPU 正在执行的指令地位和行将执行的下一条指令的地位。

上下文切换分类

  1. 过程之间的上下文切换。
  2. 线程之间的上下文切换(本文重点)。

什么场景会导致线程的上下文切换?

导致线程上下文切换的有两种类型:

自发性上下文切换是指线程由 Java 程序调用导致切出,在多线程编程中,执行调用上图中的办法或关键字,经常就会引发自发性上下文切换。

非自发性上下文切换指线程因为调度器的起因被迫切出。常见的有:线程被调配的工夫片用完,虚拟机垃圾回收导致或者执行优先级的问题导致。

那么虚拟机垃圾回收为什么会导致上下文切换?

在 Java 虚拟机中,对象的内存都是由虚拟机中的堆调配的,在程序运行过程中,新的对象将一直被创立,如果旧的对象应用后不进行回收,堆内存将很快被耗尽。Java 虚拟机提供了一种回收机制,对创立后不再应用的对象进行回收,从而保障堆内存的可持续性调配。而这种垃圾回收机制的应用有可能会导致 stop-the-world 事件的产生,这其实就是一种线程暂停行为。

怎么发现上下文切换?

vmstat 命令

能够应用 vmstat 命令来查看线程上下文切换状况。

参数阐明

procs

  • r:等等运行的过程数。
  • b:出在飞终端睡眠状态的过程数。

memory

  • swpd:虚拟内存应用状况,单位:KB。
  • free:闲暇的内存,单位:KB。
  • buff:被用来作为缓存的内存数,单位:KB。

swap

  • si:每秒从替换区写到内存的大小。
  • so:每秒写入替换区的内存大小。

io

  • bi: 每秒读取的块数
  • bo: 每秒写入的块数

system

  • in: 每秒中断数,包含时钟中断。
  • cs: 每秒上下文切换数。

CPU

  • us: 用户过程执行工夫 (user time)
  • sy: 零碎过程执行工夫 (system time)
  • id: 闲暇工夫 (包含 IO 等待时间), 中央处理器的闲暇工夫。以百分比示意。
  • wa: 期待 IO 工夫

pidstat 命令

参数阐明

  • cswch/s(被迫):值过程无奈获取所需资源导致的上下文切换,比方:I/O,内存等系统资源有余时,就会产生被迫上下文切换
  • nvcswch/s(非被迫):值过程因为工夫已到等起因,被零碎强制调度而产生的上下文切换,比方,大量过程都在抢夺 CPU 而产生非被迫上下文切换

总结

上下文切换就是一个工作的线程被另外一个线程暂停,另外一个线程占用了处理器开始执行工作的过程。零碎和 Java 程序自发性以及非自发性的调用操作,就会导致上下文切换,从而带来零碎开销。

线程越多,零碎的运行速度不肯定越快。那么咱们平时在并发量比拟大的状况下,什么时候用单线程,什么时候用多线程呢?

个别在单个逻辑比较简单,而且速度绝对来十分快的状况下,咱们能够应用单线程。例如,咱们后面讲到的 Redis,从内存中疾速读取值,不必思考 I/O 瓶颈带来的阻塞问题。而在逻辑相对来说很简单的场景,等待时间绝对较长又或者是须要大量计算的场景,我倡议应用多线程来进步零碎的整体性能。例如,NIO 期间的文件读写操作、图像处理以及大数据分析等。

举荐浏览

面试官:什么是外部类?| 这么答复就妥妥的

正文完
 0