【问题标题】:What is the difference between using Python's threading versus async/await使用 Python 线程与 async/await 有什么区别
【发布时间】:2019-09-16 07:55:33
【问题描述】:

我试图更熟悉 python3 中 asyncio 的用法,但我不知道什么时候应该使用 async/await 或线程。是否有区别,或者一个比另一个更容易使用。

那么例如在这两个函数之间,一个比另一个更好吗?

只是通用代码

def func1()
def func2()

threads = [threading.Thread(target=func1), threading.Thread(target=func2)]
for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

async def func1()
async def func2()

await asyncio.gather(func1(), func2())

【问题讨论】:

  • 核心开发者 Raymond Hettinger 的这段视频将回答你所有的问题; youtu.be/9zinZmE3Ogk

标签: python python-3.x multithreading async-await python-asyncio


【解决方案1】:

我的建议是在所有情况下都使用线程,除非您正在编写高性能并发应用程序并且基准测试表明单独使用线程太慢。

原则上,协程有很多值得喜欢的地方。它们更容易推理,因为每个非阻塞操作序列都可以被视为原子操作(至少如果您不将它们与线程结合使用);而且因为它们很便宜,所以您可以随意调整它们以更好地分离关注点,而不必担心会影响您的性能。

然而,Python 中协程的实际实现是一团糟。最大的问题是每个可能阻塞的函数,或者可能调用任何可能阻塞的代码,或者可能调用任何代码......可能调用任何可能阻塞的代码的函数,都必须用async和@重写987654323@关键字。这意味着,如果您想使用一个阻止或回调代码的库,并且您想阻止回调,那么您根本无法使用该库。由于这个原因,现在 CPython 发行版中有一堆库的重复副本,甚至内置语法的重复副本(async for 等),但你不能指望大多数模块可以通过 pip 来维护两个版本。

线程没有这个问题。如果库的设计不是线程安全的,您仍然可以在多线程程序中使用它,方法是将其使用限制在一个线程或通过锁定保护所有使用。

因此,尽管存在问题,但在 Python 中使用线程总体上要容易得多。

有一些第三方协程解决方案可以避免“异步感染”问题,例如greenlet,但您仍然无法将它们与内部阻塞的库一起使用,除非它们专门设计用于协程。

【讨论】:

  • 我同意,只要您的线程在执行 I/O 绑定操作时不持有锁(会阻止其他需要获取相同锁的线程运行),那么它会一样快并且您不必确保在底层模块中没有阻塞代码。
【解决方案2】:

使用 asyncio,一段代码可以使用 await 收回控制权。对于线程,这是由 Python 调度程序处理的。多线程采用锁定机制来防止共享内存出现问题。多线程的另一个优点是它可以使用多个内核。

如果您想阅读更多内容,这里有一篇很棒的文章: https://medium.com/@nhumrich/asynchronous-python-45df84b82434

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-25
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 2022-01-27
    相关资源
    最近更新 更多