【发布时间】:2018-06-09 18:37:12
【问题描述】:
我很难理解异步功能如何以及为什么在 python 中工作,但我仍然不确定我是否正确理解了所有内容(尤其是“为什么”部分)。如果我错了,请纠正我。
异步方法和线程的目的都是为了可以同时处理多个任务。
线程方法看起来简单直观。如果python程序同时处理多个任务,我们每个任务都有一个线程(可能带有子线程),每个线程的堆栈反映了相应任务的当前处理阶段。一切都很简单,有易于使用的机制来启动一个新线程并等待它的结果。
据我了解,这种方法的唯一问题是线程很昂贵。
另一种方法是使用async 协程。我可以看到这种方法有几个不便之处。我只会列举其中几个。我们现在有两种方法:常用方法和async 方法。 90% 的时候唯一的区别是你需要记住这个方法是async 并且在调用这个方法时不要忘记使用await 关键字。是的,你不能从普通的方法中调用async 方法。而程序周围所有这些async - await 语法垃圾只是表明该方法能够将控制权交给消息循环。
线程方法没有所有这些不便。但是async - await 方法允许处理比线程方法更多的并发任务。这怎么可能?
对于每个并发任务,我们仍然有一个调用堆栈,只是现在它是一个协程调用堆栈。我不太确定,但看起来这是关键区别:通常的堆栈是操作系统堆栈,它们很昂贵,协程堆栈只是一个 python 结构,它们便宜得多。我的理解正确吗?
如果这是正确的,那么将 python 线程/调用堆栈与 OS 线程/调用堆栈解耦以使 python 线程更便宜不是更好吗?
对不起,如果这个问题很愚蠢。我确信选择async-await 方法有一些原因。只是想了解这些原因。
更新:
对于那些不认为这个问题不好和太宽泛的人。
这是一篇文章Unyielding - 首先解释了为什么线程不好并宣传async 方法。主要论点:线程是邪恶的,很难推断一个可以同时从任意数量的线程执行的例程。
感谢 Nathaniel J. Smith(python Trio library 的作者)提出了这个链接。
顺便说一句,文章中的论点对我来说并不令人信服,但仍然可能有用。
【问题讨论】:
-
我把它写成评论是因为它没有给出完整的答案:异步是基于协作调度的。您可以确定哪些代码块将不间断地执行。您还可以确保异步代码在不与其他代码交互的情况下运行,因为没有任何东西是并行执行的——与线程不同。这使得同步、锁定和竞争条件等问题更容易处理。
-
@VPfB 谢谢,好点,我没想到。有趣的是,上周我不得不使用
threading.Lock,即使该应用程序是基于async的。代码的“关键部分”是与外部应用程序通信,重要的是,来自不同协程的一系列请求不会在时间上重叠。所以即使没有线程,同步问题也不会完全消失。
标签: python multithreading asynchronous async-await python-asyncio