Python 有 thread,为什么还要 asyncio 呢?

2017-10-08 22:21:48 +08:00
 liudaqi
偶尔会用到 thread 做异步任务,没想到什么时候用 asyncio,这两个异步有什么差别吗,理解的不是很清楚
12556 次点击
所在节点    Python
35 条回复
cheetah
2017-10-08 22:23:20 +08:00
是两种异步方案
hjc4869
2017-10-08 22:31:03 +08:00
有 urllib,为什么还要 urllib2 呢?
PythonAnswer
2017-10-08 22:33:12 +08:00
asyncio 是基于 yield 的
thread 受限于 gil, 用处不大
testcount
2017-10-08 23:06:58 +08:00
线程和协程
Kilerd
2017-10-08 23:21:11 +08:00
多进程,线程,协程,异步

这四个概念先懂了,我们再来聊聊这个问题。
DoctorCat
2017-10-08 23:23:58 +08:00
asyncio: This module provides infrastructure for writing [single-threaded concurrent code using coroutines, multiplexing I/O] access over sockets and other resources, running network clients and servers, and other related primitives.

thread: This module provides low-level primitives for working with [multiple threads (also called light-weight processes or tasks) ] — multiple threads of control sharing their global data space. For synchronization, simple locks (also called mutexes or binary semaphores) are provided.

[] 里的含义,了解下相信你就明白了。
Srar
2017-10-08 23:42:24 +08:00
虽然没写过 Python 但是还是来回答下...是来降低上下文切换所带来的性能损失.
aijam
2017-10-09 00:16:39 +08:00
1. 虽然大家(包括楼上的 @PythonAnswer )都说 thread 受限于 GIL,但是那是对 CPU bounded tasks 而言,大多情况下 thread 还是足以应付 IO bounded tasks。
2. 即使如此,应付 IO bounded tasks 时,thread 也存在两个问题,一是 thread overhead 开销较大,二是受到系统 max thread number 的限制。基于 coroutine 的 asyncio 有助于克服这两个问题。
3. 然而 asyncio 复杂的 API 还是被人诟病: https://twitter.com/mitsuhiko/status/792441114561220609
最近几年 Python3.4 以后的几个新特性都是围绕基于 coroutine 的 concurrency ( async generator in 3.6, async/await in 3.5, asyncio in 3.4 ),各个 Python 的会议也都会有关于 concurrency 话题的 talk,说明社区还在努力探索。
NoAnyLove
2017-10-09 00:42:29 +08:00
#3 楼的回答过于偏颇。并没有受限于 GIL 就让 thread 用处不大这种说法了,具体还是看应用场景,如果是计算密集的任务,为了充分利用多核,当然不会用 thread,而应该用 process。但是对于 IO 密集场景或者仅仅为了解决多路传输,那么 thread 是简单而有效的选择。而且#3 楼将两句话并发在一起,新手会以为 asyncio 不受限于 GIL 能够处理计算密集的任务。

个人认为,两者的主要差别是可以处理并发量的能力。可以根据你需要处理的异步 IO 的数量,比如:如果有 100 个 socket,那么给每个 socket 分别创建一个 thread 来处理,现在的计算机应该都能 hold 住。但是当 socket 数量更高,并发量更大的时候,那么就应该选择使用 asyncio 了。
keysona
2017-10-09 01:06:30 +08:00
楼上两位说得很好了。

一言不合就说 GIL 也是够了...

<amp-youtube data-videoid="P3AyI_u66Bw" layout="responsive" width="480" height="270"></amp-youtube>&t=1141s

也要看看使用场景好吗...
dzmcs
2017-10-09 02:24:51 +08:00
@DoctorCat 方括号里说 io 复用,这个 asyncio 也是类似 epoll 可以得到网卡中断事件?如果只是在解释器内模拟,那这个东西做 io 大的并发估计也就一般吧

thread 是否是系统线程,进入调度队列?
scriptB0y
2017-10-09 07:55:04 +08:00
billion
2017-10-09 09:15:12 +08:00
比如你需要做三件事情,用电饭煲煮饭,用洗衣机洗衣服,用砂锅煲汤。

如果你用 thread,那么就需要三个人,第一个人把饭放进电饭煲,然后等着它煮好。第二个人把衣服放进洗衣机,等着它洗好,第三个人把食材放进砂锅,等着汤煲好。准备工作做完以后,这三个人都会啥事不干,傻等着。

如果你用 asyncio,那么你只需要一个人做这个事情。他先把米倒进电饭煲,打开开关开始煮饭,煮饭的过程电饭煲自己会做,不用这个人来管。所以中间的时间,他可以接下来去把衣服放进洗衣机,打开开关,洗衣机自动开始洗衣服,也不再需要他管了。于是他再去把食材放进砂锅,开始煲汤。开始煲汤以后,短时间里他还可以去看个书。如果汤漫出来了,它会听到声音,这个时候再去查看就好了。同样的,电饭煲煮饭煮好了会有提示音,洗衣机洗好了衣服也有提示音。它只需要听到提示音再去处理就好了。没有听到提示音,他就可以去做其他事情。

综上所述,
用 thread,做多少个事情就需要请多少个人,而且还有可能这些人会同时傻等,每一个人工资(占用的系统资源)可不便宜
用 asyncio,只需要一个人就可以把所有事情全部做完。
jin6220
2017-10-09 09:26:47 +08:00
@billion 除了傻等 工作干完就不在占资源了吧 看来没必要学 thread 啊
fy
2017-10-09 09:31:40 +08:00
GIL 日常背锅
PythonAnswer
2017-10-09 10:28:22 +08:00
thread threading 就是被 gil 搞得没人用的,俺说错了?
czheo
2017-10-09 10:31:13 +08:00
@PythonAnswer 你说的没有错。
fy
2017-10-09 10:40:08 +08:00
@PythonAnswer 说的没有错,但是一 thread 并不是没人用,二在这个与 asyncio 比的场景,GIL 没锅
fy
2017-10-09 10:40:57 +08:00
应该说不能说全错
PythoneerDev6
2017-10-09 15:55:08 +08:00
GIL 日常锅

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/396021

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX