python教程

当前位置:首页 > python进阶 > 当前文章

python进阶

yield是什么?为什么可以暂停程序,让出CPU

2021-11-19 115赞 老董笔记

  学习python协程的时候可能遇见过一些古老的代码,利用生成器(yield)实现协程。通过yield可以让某个函数暂停,然后切换到当前线程内另1个函数去执行,从而实现单线程内的并发运行!这可能有点匪夷所思,在传统的认知里只有进程和线程才能实现切换,所以思想经历了三个阶段:

  1)不相信单线程内可以并发

  2)想知道yield为什么可以让出CPU

  3)进程和线程可以实现切换,为何还要多此一举设计yield

  通过向一些老师傅求教再加上个人理解,把上述三个疑问回答下

  关于第一点

  直接可以用一段代码证实,单线程可实现多个函数交替执行,打印出线程号来体现出是否在同1个线程。

start = time.time()

async def load_url(url, t):
    print(f"download {url}")
    print('----',threading.current_thread().name,threading.current_thread().ident)
    await asyncio.sleep(t)
    print(f"end...{url}")


t1 = load_url('url1', 2)
t2 = load_url('url2', 3)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(t1, t2))
loop.close()
end = time.time()
print("spent time:", end-start)
print('---',threading.current_thread().name,threading.current_thread().ident)
download url1
---- MainThread 7832
download url2
---- MainThread 7832
end...url1
end...url2
spent time: 2.988170862197876
--- MainThread 7832

  关于第二点

  yield是Python作者自己实现的一个协作和等待机制,一个线程内可能会有多个函数需要运行,可能有的函数需要等待,他们之间也可能需要互相协作,当一个函数要等待的时候,它就通过yield来告诉Python要进入等待状态。而Python维护了1个事件循环的列表,谁是什么状态都记录在案,通过不停的循环这个列表,一旦发现谁可以执行了就给它CPU用。至于怎么实现这种效果听说要研究如下源码:https://github.com/zpoint/CPython-Internals/blob/master/BasicObject/gen/gen_cn.md

  关于第三点

  进程和线程的切换是操作系统控制的,操作系统有自己一套调度算法,人是不能参与的。但是人类想对程序进行更加精细化的控制,想要最大限度的利用CPU,所以就研究出协程这个概念,操作系统是不知道有这个玩意的,这是人类在应用层投机取巧的一个设计思路。

文章评论

yield是什么?为什么可以暂停程序,让出CPU文章写得不错,值得赞赏