其实从处理器的角度看协程更符合直觉,一个处理器核心本来就没法同时处理两件事情,要同时进行多件事情本来就需要正在运行的让出处理器,然后才能去处理另一件事情。只不过这个让出的过程是线程调度器主动抢占的。
所以线程调度器是假定不同的线程是毫无关系的,所以它平均的分配时间片让处理器雨露均沾。
但是很快人们发现这不是事情的全部,很多时候两个线程不是完全独立的,他们会操作同一个资源。这个时候人们又发明了同步锁,使得一段时间内只有一个线程可以操作这个资源,其他线程只能等待。
然后我们很快发现,这特么不是脱了裤子放屁么?处理器本来同一时间就只能有一个线程在运行。是线程调度器抢断划分时间片给其他线程跑,现在其他线程又说特么我要等前面那个线程用完了这个资源才能运行。
你特么早说啊,我抢什么抢?既然你们排他性的争抢同一个资源,你们一个个的跑不就好了,我就给你们排个队就完了。
也就是说,在所有线程相互独立且不会阻塞的模式下,抢断式的线程调度器是不错的选择。因为它可以保证所有的线程都可以被分到时间片不被程序员的垃圾代码所累。这对于某些事情来说是至关重要的,例如计时器、回调、IO触发器(譬如说处理请求)什么的。
但是在线程不是相互独立,经常因为争抢而阻塞的情况下,抢断式的线程调度器就显得脱了裤子放屁了,既然你们只能一个个的跑,那抢断还有什么意义?让你们自己去让出时间片就好了。
再往后,大家发现经常有阻塞的情况下,主动让出时间片的协程模式比抢占式分配的效率要好,也简单得多。
但是线程并不是一无是处,抢断式线程调度器事实上提供了准实时的体验。例如Timer,虽然不能确保在时间到达的时候一定能够分到时间片运行,但不会像协程一样万一没有人让出时间片就永远得不到运行……
比如说像JS这种语言,你要打开控制台敲个while(true);回车……