线程切换的几个核心问题
什么是线程切换
以下概念描述来自《java并发编程的艺术》这本书。
即使是单核处理器也支持多线程执行代码,CPU是通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停的切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒。
CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以从保存到加载就是一次上下文切换。
什么机制管理了线程的切换
CPU通过时间分配算法管理线程切换
CPU上下文
CPU寄存器和程序计数器.
如果站在线程的场景回答就是线程的私有内存.虚拟机栈和程序计数器。
如何理解线程切换引起了开销这句话
切换的步骤有两步:由A线程切换至B线程运行,那么需要保存A的私有内存,加载B线程的私有内存。保存在什么地方呢。有关这个保存的位置,没有统一的说法,有说线程的栈空间,有说linux开启的一块内存。不管在哪需要CPU去执行这两个步骤,而这个切换消耗和CPU执行B线程是串行的.总结一下开销就是这保存和加载的时间开销.
引起切换的场景
- 当前执行任务的时间片用完之后,系统CPU正常调度下一个任务
- 当前执行任务碰到IO阻塞,调度器将此任务挂起,继续下一任务
- 多个任务抢占锁资源,当前任务没有抢到锁资源,被调度器挂起,继续下一任务
- 用户代码挂起当前任务,让出CPU时间
- 硬件中断
如何真实感受切换的时间
利用lmbench来真真切切感受切换带来的消耗,在linux 可以执行vmstat 1.执行效果demo如下
cs这一列的含义就是1秒中执行的切换次数,可以得知cpu切换一次消耗1ms左右,这个开销根据不同的电脑配置不同
如何面对
作为android开发人员,基本很少因为线程切换引起过卡顿问题,万计,十万级,百万级的时候如果线程太多,那么造成最多的是内存问题,那么理解线程切换会引起开销这个知识点是不是毫无实际用处,是只是存在书本中的内容。刚开始我也这么想的,当知道的越多的时候,这个知识点的魅力不在于本身,在于串联了非常多有用的知识,CPU运行任务的机制,上下文可以延申用户态,内核态,解决开销问题需要掌握无锁编程,线程池,协程。能理解了synchronized锁分成重量级,轻量级锁能提升性能的背景,知道了用户态能做的的事情有限,读取内存,io操作,硬件操作等都需要内核态来进行,接着可以思考为何要设置用户态,内核态,可以思考为何线程私有内存的作用之一保存和恢复提供数据等等延申的知识点是非常丰富的,所以线程切换是理解虚拟机,操作系统比较好的切入口.这篇文章只是起一个抛砖引玉的作用,更多的知识需要大家一起挖掘。