当前位置: 首页 > 科技观察

一个关于进程、线程、协程的故事

时间:2023-03-13 19:40:26 科技观察

很久很久以前,有两个程序,暂且称他们为旺财和小强吧。旺财和小强这两个节目都很长,每一个都有10万多行。他们两个的生命值就是在CPU上运行,把运行的结果告诉人类。CPU是一种稀缺资源,只有一个,两个必须排队轮流使用。旺财从头到尾都执行完了,放开CPU,让小强从头执行。人类将这种处理方式称为批处理。长期以来,两人相安无事。后来CPU的速度越来越快,远远超过了内存和硬盘的速度。人类认为这种批处理系统的效率有点低。你看,小强需要从硬盘读取数据的时候,CPU一直在等待。多么浪费!这个时候,我们就可以让旺财跑起来了!当然,小强的执行场景是一定要保留的:具体执行了哪一行程序指令,函数调用到了第几级,每个函数调用有哪些参数,CPU寄存器中的值……等等。事物。如果不保存小强的行刑点,从银盘中读取小强的数据后,就无法回到中断点继续执行。这个执行点连同小强的代码,就是一个执行程序,叫做“进程”。旺财和小强在运行的时候,也是转化为进程。人类还规定一个进程不能长时间占用CPU,它只能在CPU上执行一小会儿,然后马上切换到其他进程执行。旺财和小强没当回事:不就是执行一下,休息一下,然后继续执行吗!但他们不知道的是,由于超快的CPU速度,旺财和小强虽然在不断地切换着操作,但是在缓慢的人类世界里,旺财和小强似乎是在同时执行。这就是并发。(从人的角度看,小强和旺财好像是同时执行的)多年后,他们两个真正做到了并行:在一台豪华电脑里,每人分配一个CPU,他们同时执行同一时间。这是另一个故事。这时候线程旺财已经有了接口,可以访问网络了。每当它连上网络(这也是一个非常非常耗时的操作),它就得把CPU让给小强。就算王才被安排再次执行,因为网络数据还没有返回,他只能等待,也无能为力。从人的角度来说,界面根本无法操作,旺财没有反应!人类大怒,常杀旺财。旺财心中苦涩。他奇怪为什么小强没有问题。小强不是要读写硬盘吗?那也是一个缓慢的操作。小强说:“你傻啊,里面只有一个执行进程,还得等耗时操作。你看我,里面有两个执行进程(线程),一个用来读写硬盘(T1),另一个处理接口(T2),我和操作系统商量过了,如果T1在读写硬盘,我可以调度我的T2去执行,这样接口至少还能操作。旺财觉得很有意思,也采用了类似的做法,因此一个进程中至少有一个执行进程(主线程),也可以启动一个新的执行进程(线程),线程成为最小的调度单元。协程那天,旺财被一个叫生产者和消费者的问题折腾死了,两个线程,一个线程往队列里放数据,一个线程从队列里取数据,貌似是两个线程合作处理的。很麻烦,不仅需要加锁,还需要通知和等待线程,在感叹多线程编程难度的同时,旺财震惊的发现,小强用一个极其简单的方法解决了这个问题生产者和消费者,该方法的代码如下:#Producerdefproducer(c):#OthercodeswhileTrue:value=...generatedata...c.send(value)#Consumerdefconsumer():#OthercodeswhileTrue:value=yieldprint(值)c=consumer()producer(c)“这……这是怎么执行的,那个yield是怎么回事?”旺财表示不解。“很简单,看看生产者,有没有把数据发给消费者?”小强说。“是的,那么,生产者发送完数据后,是否会立即进行下一个循环?”“这是关键点,”小强说,“他们是这样执行的:”生产者发送数据后暂停运行,不进行下一轮循环。消费者实际上在value=yield处等待,直到数据到达。现在数据来了,取出来处理(value是producer发送过来的数据)。消费者在循环中再次让步,暂停执行。生产者继续下一轮循环,生成新消息并将它们发送给消费者。旺财惊讶于小强竟然可以暂停正在运行的程序,不禁问道:“你的暂停是真的停止了,还是就像Java的yield一样,让出CPU进入就绪状态?等待下一次预定运行?”““真的是暂停了,程序就停在那里,等待对方把运行的控制权交出来。”“这不是操作系统做的吗?”王才更吃惊了。“没错,”小强得意地说,“我打算把生产者和消费者这样的代码叫做‘协程’。这个协程有一个重要的特点,就是完全由我来调度和控制,操作系统介入。”“这个协程好像和线程很像,每次协程停止执行的时候,都必须保存场景,否则无法恢复执行。”旺财说。“是啊,只不过比线程更轻量而已,操作系统内核不需要参与,相当于用户态线程,协程的开销极小,可以轻松创建大量协程顺便说一句,也许你注意到我的两个协程是“协同”的,一次只能运行其中一个。实际上,我可以在底层使用一个线程来执行这两个协程。“王才表示同意:“是的,既然两个程序可以‘配合’,就不需要加锁,也不需要在代码中写wait和notify。在程序层面,可以在同步中实现异步功能方式!代码很清晰,让我创建一个协程来玩!【本文为专栏作家“刘欣”原创稿件,转载请通过作者微信获得授权♂coderising】点此查看该作者更多好文