在文章“我没有感觉到异步压力”中, Armin Ronacher进行了以下观察:
在线程代码中,任何函数都可以产生。在异步代码中,只有异步函数可以。例如,这意味着writer.write方法无法阻止。
此观察是参考以下代码示例进行的:
from asyncio import start_server, run
async def on_client_connected(reader, writer):
while True:
data = await reader.readline()
if not data:
break
writer.write(data)
async def server():
srv = await start_server(on_client_connected, '127.0.0.1', 8888)
async with srv:
await srv.serve_forever()
run(server())
我不明白这个评论。特别:
yield
在异步函数内部,为什么同步函数不能?yield
有阻塞的执行呢?为什么不能yield
,不能阻止功能?逐行进行:
在线程代码中,任何函数都可以产生。
在机器上运行的程序是按照流程进行组织的。每个进程可以具有一个或多个线程。线程(如进程)由操作系统调度(并可由操作系统中断)。在此上下文中,单词“ yield”表示“让其他代码运行”。当工作被拆分到多个线程之间时,函数很容易“屈服”:操作系统将一个线程中运行的代码挂起,在另一个线程中运行一些代码,将其挂起,然后返回,然后在第一个线程上进行更多工作,等等。上。通过以这种方式在线程之间切换,可以实现并发。
在此执行模型中,暂停的代码是同步的还是异步的都没有关系。代码中的线程正在运行的行由行,所以同步功能的基本假设---发生在运行一个代码行和下一之间---不受侵犯没有变化。
在异步代码中,只有异步函数可以。
在本文中,“异步代码”是指单线程应用程序,其功能与多线程应用程序相同,不同之处在于它通过在线程中使用异步函数来实现并发,而不是在不同线程之间进行拆分。在此执行模型中,解释器(而不是操作系统)负责根据需要在功能之间进行切换以实现并发性。
在此执行模型中,将工作挂在位于异步函数内部的同步函数中间是不安全的。这样做意味着在运行同步功能的过程中运行其他一些代码,从而破坏了同步功能所做的“逐行”假设。
结果,解释器将仅等待同步子功能之间的异步功能的执行暂停,而不会等待一个子功能。这就是异步代码中的同步函数无法产生的语句的含义:一旦同步函数开始运行,它就必须完成。
例如,这意味着writer.write方法无法阻止。
该writer.write
方法是同步的,因此,在异步程序中运行时,该方法是不间断的。如果要阻塞此方法,则它将不仅阻塞正在其内部运行的异步函数,还将阻塞整个程序。那将是不好的。writer.write
避免通过写入写缓冲区并立即返回来阻塞程序。
严格来说,writer.write
可以阻止,这样做是不明智的。
如果您需要在异步函数中进行阻止,则正确的方法是使用await
另一个异步函数。这就是例如await writer.drain()
。这将异步阻止:尽管此特定功能仍处于阻止状态,但它将正确地屈服于其他可以运行的功能。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句