问题

出于什么样的原因,诞生了「协程」这一概念?

回答
你想知道协程是怎么来的,对吧?这事儿还得从咱们写程序的时候,想要更有效地利用时间说起。

想想咱们以前写代码,尤其是处理一些需要等待的事情,比如网络请求,或者读写文件。传统的方法是,当程序发起一个请求,然后就傻乎乎地等着,什么也干不了,CPU 的时间就浪费了。这就像你点了个外卖,然后就一直坐在门口等着,看着什么也做不了。如果同时有其他事情要做,比如烧水、看书,你就得等外卖到了之后才能去做,效率太低了。

尤其是在服务器端,需要同时处理成千上万个用户的请求。如果每个请求都得等上一个完成才能继续,那这服务器岂不是要慢到家了?传统的“线程”模型虽然能解决一部分并发问题,但它也有它的开销。创建和销毁线程需要系统资源,线程切换的时候也要花费一些时间。当线程数量非常庞大时,这些开销就会变得很显著,反而影响性能。就像你同时叫了一堆外卖小哥,每个人都得有自己的交通工具、钥匙、身份信息,管理起来就特别麻烦,而且他们之间互相碍事,切换顾客的时候也要花费不少时间。

这时候,人们就想,有没有一种方式,能让一个程序在等待的时候,不用真的“暂停”整个执行,而是能把控制权“交”给其他事情做,等那个事情做完了,再“回来”继续做原来的事呢?

这个想法的核心就是,让程序自己管理“等待”和“切换”的时机,而不是完全依赖操作系统来调度线程。

协程就是这样诞生的。它提供了一种“协作式”的多任务处理方式。你可以想象成,一个程序里有几个“小助手”,每个助手都在忙自己的事。当一个小助手发现自己需要等待某个外部事件(比如网络响应)时,他不会像线程那样直接“罢工”,而是会主动把手里的活儿交给另一个小助手,然后自己先去休息一下,等外部事件来了再被叫醒。这样,CPU 的时间就被充分利用了,不会因为某个任务在等待而闲置。

这就好比你点外卖,外卖小哥来送餐了。你不用像之前那样傻等着,而是可以跟他说:“你把外卖放在门口,我等下出来拿。” 然后你转身就可以去做别的事情。等到你方便的时候,再去门口取外卖。这个过程中,你的时间没有被完全占用,CPU(也就是你)也可以去做其他事情。

所以,协程的诞生,最根本的原因是为了更高效地利用计算资源,特别是在面对大量 I/O 密集型任务时,避免线程因等待而造成的资源浪费和性能瓶颈。 它通过让程序自身更灵活地控制任务的执行和切换,实现了一种轻量级的并发,使得在同一个线程中可以同时处理多个“看起来”是并行执行的任务。这对于构建高性能、高并发的应用程序来说,是非常重要的一个进步。

网友意见

user avatar

其实从处理器的角度看协程更符合直觉,一个处理器核心本来就没法同时处理两件事情,要同时进行多件事情本来就需要正在运行的让出处理器,然后才能去处理另一件事情。只不过这个让出的过程是线程调度器主动抢占的。

所以线程调度器是假定不同的线程是毫无关系的,所以它平均的分配时间片让处理器雨露均沾。

但是很快人们发现这不是事情的全部,很多时候两个线程不是完全独立的,他们会操作同一个资源。这个时候人们又发明了同步锁,使得一段时间内只有一个线程可以操作这个资源,其他线程只能等待。


然后我们很快发现,这特么不是脱了裤子放屁么?处理器本来同一时间就只能有一个线程在运行。是线程调度器抢断划分时间片给其他线程跑,现在其他线程又说特么我要等前面那个线程用完了这个资源才能运行。

你特么早说啊,我抢什么抢?既然你们排他性的争抢同一个资源,你们一个个的跑不就好了,我就给你们排个队就完了。


也就是说,在所有线程相互独立且不会阻塞的模式下,抢断式的线程调度器是不错的选择。因为它可以保证所有的线程都可以被分到时间片不被程序员的垃圾代码所累。这对于某些事情来说是至关重要的,例如计时器、回调、IO触发器(譬如说处理请求)什么的。

但是在线程不是相互独立,经常因为争抢而阻塞的情况下,抢断式的线程调度器就显得脱了裤子放屁了,既然你们只能一个个的跑,那抢断还有什么意义?让你们自己去让出时间片就好了。

再往后,大家发现经常有阻塞的情况下,主动让出时间片的协程模式比抢占式分配的效率要好,也简单得多。

但是线程并不是一无是处,抢断式线程调度器事实上提供了准实时的体验。例如Timer,虽然不能确保在时间到达的时候一定能够分到时间片运行,但不会像协程一样万一没有人让出时间片就永远得不到运行……

比如说像JS这种语言,你要打开控制台敲个while(true);回车……

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有