计算机同时跑好几个程序时,里面的 CPU 到底怎么选谁先用呢?这个决定不是随便来的,操作系统有个专门负责这事的调度程序。当多个进程或线程同时申请 CPU 时间,系统会按不同算法分配。比如你开视频软件同时下载东西,后台程序会不会突然卡住,都和这里有关。
调度方式分抢占式和非抢占式两种。非抢占式像电影院买票,买了票就得看完电影。程序拿到 CPU 时间后一直跑,除非自己主动让出来或者等 I/O 操作。缺点很明显,一个程序死活不放手,其他程序只能干等。这时候就需要抢占式调度,CPU 时间像共享单车限时骑,到了时间必须下车,换下一个人。这种模式靠系统时钟中断实现,但设置时间太短会频繁切换浪费资源,太长又影响用户体验。
批处理系统常用最短作业优先算法,就像食堂窗口按打饭速度排序。系统预测哪个程序计算快,先让计算量小的跑,整体效率高。但预测不准会出大问题,万一短任务变长或者新任务突然来,后面程序的等待时间反而更长。医院的挂号系统用这方法,病人按预计诊疗时间排队,能减少整体等待时长。
交互式系统用得最多的是轮询算法,给每个程序定时时间段。比如你的电脑有二十个进程,每个能用 CPU 十秒,时间到就轮下一个。但时间片设多少很讲究,设五毫秒切换太频繁,系统忙活管理没空干活;设三十秒又可能出现简单任务等太久。类似排队叫号系统,间隔过短或过长都会出乱子。

线程调度比进程更复杂。用户级线程切换像班干部管纪律,CPU 空闲时选好进程,里面线程自己内部调。但线程卡在 I/O 读取时会拖慢整个进程。内核级线程直接由系统管,切换成本高但灵活,像交警指挥交通,每个线程单独安排。安卓系统用的就是后者,多开 app 不会因一个线程卡死整个进程。
实时系统需要严格时间限制,比如飞机自动驾驶,错过一秒就危险。硬实时必须准时完成任务,调度算法提前规划好时间表,绝不允许超时。软实时像视频播放,偶尔延迟几帧可以接受,但长期卡顿就不行。工厂流水线控制系统用硬实时,每个环节时间误差超过毫秒就会停机。

线程切换耗资源,换成内核级线程其实更慢?因为换进程时需要改内存映射和缓存,用户级线程自己换内部状态快多了。但用户级线程遇到 I/O 阻塞就会连累整个进程,得系统调度新进程才能解围。游戏程序常用用户级线程,减少系统调用开销,提升画面流畅度。
调度算法不公平问题常被抱怨。优先级高的程序永远排前面,普通用户进程只能抢残羹冷炙。微软系统的空闲进程占 CPU 资源,实际是系统模拟的假进程,用来显示空闲状态,占着茅坑不拉屎。难怪有时候明明啥都不干,任务管理器显示 CPU 占用还有 10%。

了解这些后,下次电脑卡的时候,大概能猜到是不是调度算法没调好。系统底层运作远比表面复杂,一个小参数调整就能影响整机性能。这些看不见的程序默默决定着你用电脑的流畅体验,却从不在用户面前显摆。