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

2017-10-08 22:21:48 +08:00
 liudaqi
偶尔会用到 thread 做异步任务,没想到什么时候用 asyncio,这两个异步有什么差别吗,理解的不是很清楚
12727 次点击
所在节点    Python
35 条回复
wizardforcel
2017-10-09 21:09:46 +08:00
@dzmcs 是系统级线程,但是只能映射到单个核。
wizardforcel
2017-10-09 21:12:27 +08:00
@dzmcs 虽然都只能利用单个核,但是 asyncio 没有上下文切换,优势在这里。
wizardforcel
2017-10-09 21:18:09 +08:00
另外 asyncio 也有缺陷。就是你如果用了它,所有 io api 都要用异步(支持多路复用)的版本。要不然还是卡着。这就意味着可能很多库就不能用了。
dzmcs
2017-10-09 21:30:39 +08:00
@wizardforcel 看了下 thread 实现,是模拟线程,不是系统级线程,至少 2.7 的实现是模拟的
NoAnyLove
2017-10-09 23:18:22 +08:00
@PythonAnswer 不要总是甩锅给 GIL,到底是怎么得出结论没人用 threading 的啊?

@wizardforcel 如果没有对应的 aio 库,把同步的操作丢给线程池来处理也是可以的。目前的异步文件操作( aiofile ),DNS 查询等操作,其实都是放在线程池里面的。真正能够高效处理的还是只有 socket。

@dzmcs 不知道该说些什么。。。。。。
DoctorCat
2017-10-09 23:33:47 +08:00
@dzmcs 除了 opcode 外我大 Py 从来都不自己模拟东西好伐,至少在 Linux 下都是依赖 syscall 的。所以 thread 也是 syscall,只是从 VM 层面和开发者层面封装了一些,同时也加锁保护 VM 执行栈,所以才有了 GIL。

可以具体看一下模块源码,不是特别难懂的。
DoctorCat
2017-10-09 23:44:10 +08:00
@dzmcs 回复 24 楼的观点,我不清楚你所谓的 [模拟] 指的是啥,但可以看看代码: https://github.com/python/cpython/blob/master/Modules/_threadmodule.c#L1023
https://github.com/python/cpython/blob/731e18901484c75b60167a06a0ba0719a6d4827d/Python/thread_pthread.h#L201
Linux 下是 pthread 实现的
guyskk0x0
2017-10-09 23:51:46 +08:00
程序通常会遇到三种瓶颈:CPU,IO,内存
对策也有三种:多进程,多线程,异步 io/协程

多进程能利用多核 CPU,但内存开销大。

多线程在操作系统层面可以利用多核 CPU,但各种线程同步 /锁的问题,会导致 Python 解释器实现特别复杂,所以干脆加了个全局锁,只允许用一个核;线程在执行 io 操作阻塞时,系统会把线程挂起,把 CPU 分配给别的线程运行;内存开销比进程小。

异步 io 相当于在 Python 中实现
asyncio/协程相当于在 python 中实现一个内核 /调度系统,协程在进行 io 阻塞时,安排别的协程继续运行;内存开销更小。

如果你遇到 io 瓶颈,可以用多线程和协程,协程内存开销更小,能同时跑更多任务,web 服务能同时处理更多请求。

PS:asyncio 实现过于复杂,推荐 curio !
guyskk0x0
2017-10-09 23:58:20 +08:00
@wizardforcel 会 io 阻塞但没有异步 io 实现的库,可以用线程池封装成异步,也就是异步 io 和多线程可以一起用:P
dzmcs
2017-10-10 01:01:35 +08:00
@DoctorCat
我错了
看了 threadmodule.c,没有 grep 到 pthread_create,看文件又这么长,以为是模拟的线程
是系统线程,那为啥老说 python 线程性能差呢?
PythonAnswer
2017-10-10 01:31:32 +08:00
thread 模块被更高级的 threading 模块代替了。

由于 gil 的存在,threading 并不能提高 cpu 密集运算的性能。threading 以前用于提高 io 密集型的操作速度。

py3 新加的 asyncio 是用来做异步 io 的。

我很久没用 threading 了,并没有不适。
DoctorCat
2017-10-10 11:42:27 +08:00
@dzmcs 据说单核那个年代 Guido 在设计时偷懒了加了 GIL,没考虑过多核…
justff
2017-10-10 14:13:16 +08:00
@DoctorCat 一直很费解,为什么这么多年了都不改进 cPython 的解释器
wizardforcel
2017-10-10 14:34:18 +08:00
@dzmcs 因为系统级线程和处理机(核)之间还有个映射,GIL 把这些线程都限制在一个核上了。
DoctorCat
2017-10-10 22:39:38 +08:00
@justff 社区有人尝试过的,都没啥成效。别指望 CPython 改了。
其实放在 Web 开发领域也并无大碍,毕竟也胶水语言,可以放到本地线程栈去做计算密集,比如用 Cython 重写部分业务代码。

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

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

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

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

© 2021 V2EX