以前有一帮医生,帮一个城市看病。当然,医生少人多,政府就开始动脑筋,怎么样让医生给更多的人看病。

最开始是医生去病人那里看病的,医生花在路上的时间很长,于是成立了医院。让病人过来,节省医生的时间。当然,病人肯定比医生多的,这是整个文章的假定。为了保持原来的模式,病人到了医院后,会有自己独立的一间屋子,完全模拟在家的感觉。这样会有什么问题呢?问题在于病人独占了医生,在病人抽血,验血的时候,医生无所事事,因此效率很低。

后来转换了一个模式,医生过一段时间就离开当前病人,看看哪个病人那里空着就过去。这样的目地是为了防止一个病人拉住医生不放,将医生的时间平均分配到多个病人头上。这样的动作快多了,但是医院受不了了。原本8个医生,一人一个病房。现在8个医生要在N间屋子里穿梭,万一每个屋子里的病人都是在抽血,那这个N就会无穷大了,现在是屋子不足了。

然后又换了个模式,对不起,现在不是一人一间屋子了,是一堆人一间屋子。每个人只要一个床和一个病例记录,其他的设备可以有限的共享。这样屋子不足的问题得到了部分的缓解。问题是医生又不干了。一方面离开病人再找空病人费事又费精力,另一方面抢设备也是个困扰。医生需要设备的时候会让护士去看看,如果有就拿过来。可是两个医生一起下这个医嘱就会出问题,一个护士看看还有,回去说有,再去拿的时候另一个护士已经拿着最后一个离开了。就算是同一个医生,下这个医嘱的时候,两个执行的护士也会这么打起来。

医院方面动了动脑筋,干脆这样吧。一个病房里只能一个医生负责,多个病房公用的设备看到有就可以预定起来。这样病房里的设备是不会抢起来的,而病房外的设备先到先得,也算公平。医生在病人去抽血等等活动的时候再离开病人,而不是每隔固定的时间。每隔一个很长的时间护士会去巡房,如果医生还在被同一个病人纠缠,护士就会让这个病人强制休息。

不知道有多少人看懂了?下面是答案。

第一种模式叫做服务队列模式。医生是资源池,病人是待处理请求。这个模式的问题是请求过程中往往会有大量IO出现,此时CPU陷入等待,很不合算。

第二种模式叫做多线程。医生是CPU,病房是进程。一个病人新建一个进程,系统将CPU在多个进程间调度。此时的问题是进程对系统资源的消耗比较大。

第三种模式叫做多线程,医生是CPU,病房是进程,床是线程。每个请求新建一个线程,CPU在多个线程间调度。此时系统资源消耗的问题得到一定缓解,问题变成上下文切换和资源锁定造成的浪费。

第四种模式叫做协程。CPU只在必要的时候离开当前请求。什么是必要的时候呢?就是大规模IO之前。IO完成后,CPU会再度调度回来,这样避免了频繁的上下文切换。而在一个CPU的情况下,这样的模式不会造成竞争。(多线程模式就算只有一个CPU一样竞争,因为CPU可能在任何时间离开线程,包括原子操作内部)

沈游侠曾说过,好的构架是让瓶颈只出现的CPU上。当然,从更广义的来说是只让瓶颈出现在最紧张的资源上。显然,如果是服务器,CPU和总线带宽多数是最紧张的资源。