调度算法(二)

说完 SJF 算法,我们再来看看一个新的问题。

如果,所有的任务并不是同时进入队列怎麽办?

SJF 算法之所以成立,很重要的一点是:我们知道队列里所有 job,并且比较了它们。假如,哪怕是 1s,两个任务先后进入了队列,我们的 CPU 可能就无法比较它们,然后找出最短的 job,SJF 算法也就崩分离析,变回了 FIFO。

爲了解决这个问题,我们在 SJF 的高度上,再做一点修改。

最先能完成的先来 STCF (Short Time-to-Completion First)

前面的两个算法,无论是 FIFO 还是 SJF 都是按顺序执行的,也就是说,队列前面的 job 没完成,是不能执行后面的 job。

这点有点违背现实。我们煮水时,是不会等水煮完再去洗杯子,而应该是等水开的时间里去洗。虽然这个例子并不适用于我们要说的这个算法,但理念是相同的:我们可以中断任务,然后执行其它任务。

现在任务 A 是 100s 完成,B 是 10s 完成。还是最开始的问题:如果两个 job 先后进入队列里,应该怎麽办?

在 SJF 里,如果 B 先进那还好,A 先进入的话,就出问题了。因爲 A 进入时,队列里还没有任何 job,那麽 CPU 理所当然的认爲 A 是最短的任务,然后执行它。这时候再进入 B,已经是执行 A 之后的事了,B 只能乖乖等 A 执行完。那麽 Turnaroud Time 平均时间和 FIFO 是完全一样的。

\[100+1102=105s\cfrac{100+110}{2} = 105 s 2100+110​=105s\]

换成 STCF,如果 A 先后进入队列里,B 在进入,会发生什麽?首先,在 B 进来之前,A 是最短可完成的 job。在执行 1s 之后,队列 B 进来了。队列一看,发现 B 才是最短可完成的 job。于是 CPU 会中断,(关于 job 之前的切换,以后再提)然后换成执行 B,等 B 完成之后,再执行 A。

\[10+10+1002=60s\cfrac{10+10+100}{2} = 60 s 210+10+100​=60s\]

减少近一半的时间。所以,这麽优化是值得的。这几乎是我们能想到,最优的算法了吧?

RR(Round Robin)

如果之满足于 Turnaroud Time ,那麽我们的任务应该在 STCF 提出时就结束了。但我们不能只满足于 Turnaroud Time 。

假想,如果有三个 job,每一 job 都要花 1000s,在第一个 job 完成之前,你得等到 1000s 之后,才能看到第二个 job 开始工作。天!我想要知道自己输进去的式子有没有问题,必须等到 1000s 后,才能看到第一次运行!响应太慢了!

能想到最简单的办法,就是加快 STCF 的切换过程。比如,A 执行几秒,B 执行几秒,这样不停的切换就好了。这也是 Round Robin 算法的核心。

不过,如果这样的法,STCF 的关键最短可完成就没了,同时,频繁切换进程也会产生很大的花销,切换得越快,花销就越多,这样是否值得?换而言之,我们 STCF 算法依然不是我们想要的,最优的,算法。

最关键的问题

我们要找到一个算法,它的 Turnaroud Time 期望最小,同时,还要很快的响应。这才是我们的目标。

还有,我们还要解决从最开始就设下的,绝对不可以忽视的,上面所有算法的根基条件。破坏这个条件,也意味着,上面的一切算法将会轰然倒塌,那就是:我们无法知道任务的运行时间。