asyncio和threads 区别、对比学习

目前存在非常多的问题
诸如

asyncio到底是什么?
asyncio满足什么需求?
asyncio和threads的关系和区别是什么?满足的需求一样吗?
await一个async的函数,难道不是和直接运行不是async的这个函数等价吗?那await和async存在的意义是什么?
等等。。。

中文网站资料甚少,很多教程都过于晦涩。于是便求助于英文文献,本文记录一些阅读时让我产生顿悟感的内容,并人工翻译。

以下中文均为人工翻译,非机翻。

A coroutine is a function that can be suspended and resumed.
coroutine: Coroutines are a more generalized form of subroutines. Subroutines are entered at one point and exited at another point. Coroutines can be entered, exited, and resumed at many different points

Coroutine是一个可以暂停和恢复的函数。
Coroutine: Coroutines是子程序的一种更概括的形式。子程序在一个点进入,在另一个点退出。Coroutines可以在许多不同的点进入、退出和恢复

coroutines are the unit of concurrency used in asyncio programs.

coroutines是asyncio程序中使用的并发单元。

A coroutine may suspend for many reasons, such as executing another coroutine, e.g. awaiting another task, or waiting for some external resources, such as a socket connection or process to return data.
Many coroutines can be created and executed at the same time. They have control over when they will suspend and resume, allowing them to cooperate as to when concurrent tasks are executed.

一个"协同程序"可能因为很多原因"卡住",如执行其他协同程序,举几个例子,等待其他任务,或者等待一些外部资源,如连接网络、等待程序返回值。
很多个“协同程序”可以同时被创建并执行。他们能控制何时暂停、何时恢复。允许他们在“并发任务”被执行时合作。

This is called cooperative multitasking and is different from the multitasking typically used with threads called preemptive multitasking tasking.

这被称为“合作式多任务,他和通常用“线程”实现的多任务不同,用“线程”实现的多任务被称作“抢占式多任务”。

其实看到这里,还是云里雾里,太过于理论。
大概知道asyncio和thread都是用于实现“并发任务”,但是还是不能了解到asyncio具体和thread的区别。
这篇文章也缺乏很具体的例子。
于是转而请教chatgpt,发现收获巨大,不得不感叹chatgpt太吊了。
在这里插入图片描述
这段话看完后,我又在文章里看到了这段话

Limited I/O Tasks vs No Limit on I/O Tasks

Asyncio is specifically focused on offering non-blocking I/O.

This includes I/O with commands running in subprocesses and I/O with streams for TCP network connections.
Other types of I/O can be performed in asyncio, but must be simulated using threads or processes under the covers.
Threading is suited to I/O-bound tasks, almost without exception.
Any I/O performed in Python will involve the GIL being released, allowing multiple threads to execute at the same time.
This involves more than subprocess and socket I/O but may also include file I/O and I/O with all manner of devices.

chatgpt说asyncio主要用于“io-bound”的工作,比如说频繁的读写。而thread用于“cpu-bound”工作。
而文章说asyncio是non-blocking io,but threads更是和io-bound的工作。
这不就和chatgpt说的相互矛盾了吗。
于是继续请教chatgpt,
得到以下答复,不知道是不是对的

As a result, threads in Python are typically used for I/O-bound tasks, where the thread can perform other work while waiting for the I/O operation to complete. However, because threads use blocking I/O operations by default, they can be less efficient than other approaches for performing non-blocking I/O, such as using asynchronous I/O with the asyncio library.

因此,Python中的线程通常用于I/O-bound的任务,线程可以在等待I/O操作完成时执行其他工作。然而,由于线程默认使用non-blocking I/O操作,它们的效率可能低于其他执行non-blocking I/O的方法,例如使用asyncio库的异步I/O。

这段话翻译成中文还是看得云里雾里,怎么感觉这个逻辑有问题呢?哎,chatgpt的回答可能是错的。继续追问

Are both asyncio and threading in python non-blocking I/O?
chatGpt:asyncio in Python is designed for non-blocking I/O, while threading is based on blocking I/O by default.
asyncio uses an event loop and coroutines to perform non-blocking I/O operations. Coroutines are functions that can be paused and resumed without blocking the thread, allowing the event loop to switch between tasks as needed. This allows asyncio to perform I/O operations without blocking the main thread, resulting in better performance and responsiveness.
On the other hand, threading in Python uses blocking I/O operations by default. When a thread performs a blocking I/O operation, it causes the thread to block and wait until the operation completes. During this time, the thread is unable to perform any other tasks, and any other threads that are waiting to run are also blocked.
However, it is possible to use non-blocking I/O with threading in Python by using techniques such as asynchronous I/O and non-blocking sockets. By using these techniques, you can perform I/O operations without blocking the thread, allowing the thread to continue executing other tasks while waiting for I/O operations to complete.

不知道是我英语差的问题还是chatgpt的问题,这段话我也读得云里雾里,所以在这里不做翻译。看不懂,只能继续google,直接根据我阅读时产生的疑问的三个关键词
asyncio
threading
io
然后google这三个关键词,看到了一篇stackoverflow文章
直呼Stack Overflow大法好!

在这里插入图片描述

这是多么优雅,多么言简意赅,一大堆疑问瞬间烟消云散。

类型适用场景
asyncio存在很多很慢io任务的工作,
threading存在一些较快的io任务的工作
multiprocessing大量cpu计算的工作

这个回答
我也进行了摘要,写的很好

Imagine a program that sends lots of HTTP requests to the web. If you used a single-threaded program, it would stop the execution (block) at each request, wait for a response, and then continue once received a response. The problem here is that your CPU isn’t really doing work while waiting for some external server to do the job; it could have actually done some useful work in the meantime!

想象一下,现在有个程序,要像许多网站发送许多HTTP请求。如果你用单线程的程序,在每次执行一个HTTP请求后(译者加,网络差,可能要等待非常久),程序就得暂停,等待这个HTTP请求得到响应,然后再继续执行下去。问题就出在这里,在等待外部的服务器响应你的HTTP请求时,你的CPU就是真的在“干等着”,没干任何事,但实际上可以利用这些时间做些有用的事情,(译者加:如继续响应用户从gui界面的输入,发起新的HTTP请求,渲染上一个HTTP请求返回的HTML页面,进行一些数据分析)。

The fix is to use threads - you can create many of them, each responsible for requesting some content from the web. The nice thing about threads is that, even if they run on one CPU, the CPU from time to time “freezes” the execution of one thread and jumps to executing the other one (it’s called context switching and it happens constantly at non-deterministic intervals). So if your task is I/O bound - use threading.

这里提供的解决方案是多线程(threads),你可以创先很多线程,每个线程负责请求不同的网站,这些任务同时进行。多线程美妙的地方就在于,即便他们运行在一个cpu上(译者加,cpu实际上有多核,这里指的应该是运行在单个核上的意思),cpu也能是不是的“暂停”一个线程,然后让另外一个线程继续执行(这被称为上下文切换,它以非确定性的间隔不断发生),所以如果你的任务是IO-bound,用threading。

这里引用Stack Overflow里的某个评论:I/O bound means your program spends most of its time talking to a slow device, like a network connection, a hard drive, a printer, or an event loop with a sleep time.

asyncio is essentially threading where not the CPU but you, as a programmer (or actually your application), decide where and when does the context switch happen. In Python you use an await keyword to suspend the execution of your coroutine (defined using async keyword).

(译者加,这段是关键)asyncio 本质上、大体上也是threading,但是区别是,控制context switch在哪、何时发生的,是你,或者说是你的程序,而不是由cpu。你用await关键字来暂停coroutine(用async关键字来定义)

好了,看了那么多文章,也累了,是时候回看本文开头提到的问题,看看是否能解答。

asyncio到底是什么?

一种多任务并行的工具。

asyncio满足什么需求?

解决存在大量,或者速度很慢的IO任务的工作。

asyncio和thread的关系和区别是什么?满足的需求一样吗?

关系区别正如上文。满足需求也正如上文。

await一个async的函数,难道不是和直接运行不是async的这个函数等价吗?那await和async存在的意义是什么?
等等。。。

是的,等价。在单线程的任务里是没有意义。在其他应用场景存在意义
举个例子,现在要做三件事,用洗衣机洗衣服,洗完衣服后摇晾衣服,还要吃个饭,而用洗衣机洗衣服和吃个饭是可以同时进行的,但晾衣服必须等洗衣机洗完衣服完成才能做,所以我们async 洗衣机洗衣服(), async 吃饭(),这两个同时进行,等这两个都进行完,await 洗衣机洗衣服()
await 吃饭(),然后我们在 晾衣服()

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值