V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
shinonome
V2EX  ›  Python

在可以用协程的情况下是不是多线程已经完全没有意义了

  •  
  •   shinonome · 88 天前 · 8443 次点击
    这是一个创建于 88 天前的主题,其中的信息可能已经有所发展或是发生改变。

    协程更加的灵活,同时相比于多线程,开销也更小了,

    感觉 python 在有锁的情况下感觉除非不支持协程,不然没有必要多线程了

    70 条回复    2024-07-06 16:19:30 +08:00
    amlee
        1
    amlee  
       88 天前
    cpu 密集的应用不管了?
    Ericcccccccc
        2
    Ericcccccccc  
       88 天前   ❤️ 7
    不是一回事都...

    要解决的问题也不一样
    BeautifulSoap
        3
    BeautifulSoap  
       88 天前   ❤️ 3
    不是,lz 是真的没理解什么是协程什么是线程啊,,,,,
    shinonome
        4
    shinonome  
    OP
       88 天前
    @amlee #1 CPU 密集的 python 的多线程和协程感觉区别也不大啊,Python 不是也不能同时运行多个 CPU 吗
    shinonome
        5
    shinonome  
    OP
       88 天前
    @BeautifulSoap #3 现在确实感觉这两个在 python 下太接近了
    mixuxin
        6
    mixuxin  
       88 天前
    #3 协程和线程的区别可以去参考 go 方面的资料,比较多
    ysc3839
        7
    ysc3839  
       88 天前 via Android
    无栈协程是有多线程模式的,比如 C++的 asio 能在多个线程上跑 loop 。
    BBCCBB
        8
    BBCCBB  
       88 天前
    python 有 GIL 的时候只有 1 个线程跑协程, 没 GIL 多个线程同时跑多个 task 队列..
    neilp
        9
    neilp  
       88 天前   ❤️ 1
    协程需要主动放弃.
    而有的任务中, 没有合适的时机主动放弃. 放弃太多,性能跟不上. 放弃太少,有的协程就饿死了.
    wizardyhnr
        10
    wizardyhnr  
       88 天前
    3.13 已经有 noGIL 的实验性 build 了,楼主了解一下?
    noqwerty
        11
    noqwerty  
       88 天前 via iPhone
    @shinonome 官方的 multiprocess 和第三方的 mpire 了解一下?
    fkdtz
        12
    fkdtz  
       88 天前
    我认为是的,这么说吧如果是一个全新项目不需要考虑兼容已有的代码和库,肯定是首选协程。
    至少没遇到过能用协程而不用,反而选择用多线程的情况。
    shinonome
        13
    shinonome  
    OP
       88 天前
    @noqwerty #11 是线程啦,不是多进程
    shinonome
        14
    shinonome  
    OP
       88 天前
    @wizardyhnr #10 这个太新了,我估计我最近几年都不会去使用这个版本的
    shinonome
        15
    shinonome  
    OP
       88 天前
    @neilp #9 确实,手动释放这个也挺麻烦
    weyou
        16
    weyou  
       88 天前 via Android
    楼主的话没错,但协程需要从上到下都支持才能用,直到现在 pypi 库里也没多少库是支持协程的,所以很多情况下只要你需要使用第三方库,你就不得不用线程
    dearmymy
        17
    dearmymy  
       88 天前
    也就 io 多地方适合,或者 ui 上逻辑用写成写也不错,逻辑不会回调满天飞。 其他情况协议没有扔出去得时间。
    我是觉得能真正理解协程整个实现,绝对是对编成理解上个台阶。涉及对栈,寄存器之类的理解。强烈建议 op 花时间好好研究下协程,受益匪浅。
    第一次看是一个 360 大神,一个 h 头文件写的协程库,简直惊为天人。
    jianchang512
        18
    jianchang512  
       88 天前
    多线程显然比协程更简单啊,也更少出 bug
    yidinghe
        19
    yidinghe  
       88 天前 via Android
    协程是对线程的抽象和封装,是对线程更高效的使用方式。所以有协程可用,肯定是比直接用线程好的。
    Inn0Vat10n
        20
    Inn0Vat10n  
       88 天前
    99%的正常业务场景用不到协程
    fanhed
        21
    fanhed  
       88 天前
    CPU 密集就线程, io 密集就协程, 这两者各有擅长, 一起配合才是王道
    mayli
        22
    mayli  
       88 天前
    应该只有超高并发有携程的需求,io 密集到一定程度,携程也没啥优势。
    感觉只有高并发是硬需求
    NXzCH8fP20468ML5
        23
    NXzCH8fP20468ML5  
       88 天前 via Android   ❤️ 12
    上面说什么线程适合 cpu 密集型,协程适合 io 密集型,基本上都在胡说八道。

    协程的本质是一种在允许在应用态自定义的任务调度策略/方式/单元。
    线程本质则是系统自带的任务调度策略/方式/单元,对应用是透明无感的。

    只是某些场景只用线程的话,导致线程过多,线程切换导致大量无意义的性能开销,为了避免线程的频繁切换,因此搞出了协程。

    协程是要以线程作为载体的!!!你起一百万个协程,底层还是要起几十个线程去执行这些协程,只不过这些协程的切换完全可以由应用自定义协程的调度策略(一般由运行时或编译器来做这件事情)。

    常见协程的误区:

    协程也可以是抢占式的,比如 go 的协程调度就是抢占式的。

    cpu 密集型应用一样能适用于协程。
    比如说 dataframe OLAP 引擎,就是用 tokio 的协程做任务调度。没做什么调整就得到了很高的性能。
    其他 OLTP 引擎,一般都是 Cpp 或者 Java ,没有完善的协程机制,导致不得不实现 pipeline 模型的做自定义算子调度,复杂度大大提高。
    moudy
        24
    moudy  
       87 天前
    windows 95 相对于 windows 3.2 的升级就是从携程变成了线程,亲
    netabare
        25
    netabare  
       87 天前
    没有线程哪来的协程?

    或者 op 想说的是手写线程池动不动开个新线程那种做法?
    anjingdexiaocai
        26
    anjingdexiaocai  
       87 天前 via Android
    虽然刚接触协程,看这个帖子,感觉 v 站上菜鸟还真挺多的,协程是语言层面上可控的一种轻量级线程,本来就是基于多线程,怎么会用不到…
    leonshaw
        27
    leonshaw  
       87 天前 via Android
    线程之于协程就像 CPU 逻辑核之于线程。想一下在有线程的情况下 SMP 是不是没有意义了。有 GIL 另说。
    echo1937
        28
    echo1937  
       87 天前
    如果是 Java 的 Project loom 这种有栈协程,无脑协程其实也没啥,就是会有一些问题;

    1、cpu密集型的任务并不会快
    2、执行的任务中不能有被pin住的操作,比如第三方库里很常见的 synchronized 锁和 native frame
    skuuhui
        29
    skuuhui  
       87 天前
    目前开来,在 python 目前现状中,协程确实是最好的选择了,因为有解释锁+上下文切换,线程在 python 中似乎怎么也无法上得了台面。
    shinonome
        30
    shinonome  
    OP
       87 天前
    @netabare #25 emmm 嗯,是这样想的
    Austaras
        31
    Austaras  
       87 天前   ❤️ 3
    非要咬文嚼字的话协程从定义上来讲就是不能抢占的,go 那个也不叫协程啊它叫 go 程 goroutine
    hefish
        32
    hefish  
       87 天前
    python 支持多线程了? 哪个版本开始的?
    k9982874
        33
    k9982874  
       87 天前 via Android
    协程理解成线程语法糖就行了,底层由语言决定使用什么策略分片,不需要想太多。
    当然考八股就当我没说
    GeekGao
        34
    GeekGao  
       87 天前   ❤️ 1
    细品:在一个应用中,可使用多线程来处理 CPU 密集型任务,同时使用协程来处理 IO 密集型任务。
    NoobPhper
        35
    NoobPhper  
       87 天前
    又来个小子
    shinonome
        36
    shinonome  
    OP
       87 天前
    @GeekGao #34 但是这在 python 中也是吗,python 中多线程也处理不了 CPU 密集的呀
    shinonome
        37
    shinonome  
    OP
       87 天前
    @NoobPhper #35 这不是来虚心请教大家嘛
    shinonome
        38
    shinonome  
    OP
       87 天前
    TVT 这是 python 分区啊,你们说的其他语言我也不懂啊,python 多线程有锁啊
    GeekGao
        39
    GeekGao  
       87 天前
    @shinonome
    不是处理不了,是 CPython 目前多线程效率低,但是其他 NoGIL 的 Python 实现一样可以哇,例如 IronPython 。
    而且,可以把 CPython 线程模块换成多 multiprocess 就好了嘛。
    leegoo
        40
    leegoo  
       87 天前
    python 应该也有线程池的把。
    我想楼主 是不是想表达
    以前做一些耗时任务的时,都是把任务丢到线程池里面去
    那么现在有协程的话,是不是可以省略创建线程池,把任务放到线程池里面动作,也可以减少线程池的维护工作

    并不是纠结协程是怎么来的
    jurassic2long
        41
    jurassic2long  
       87 天前
    在 python 中,因为 gil 的存在,协程和线程在资源利用率上确实差不多。但是线程还有个巨大的优势——编程简单,协程编程,如果不是有经验的老师傅,肯定被绕晕的
    foxthree
        42
    foxthree  
       87 天前
    @GeekGao multiprocess 不就是多进程吗,python 目前的大多数应用中不还是 CPU 密集---多进程,IO 密集---多线程吗
    hayala
        43
    hayala  
       87 天前
    @xxfye 你字多,信你的
    0xD800
        44
    0xD800  
       87 天前
    多年前我还想用易语言实现一个 fiber 调度器,要做的东西太多了,就没做了。。不过易语言有个 LING 好像做了,hook 了很多 api 。
    kaminic
        45
    kaminic  
       87 天前
    协程只是用户层轻量级的任务调度单元,背后还是需要靠线程去执行,比如 GO 的 M:N 模型,M 个协程背后 N 个线程调度执行
    RockShake
        46
    RockShake  
       87 天前
    最简单的说法你可以认为协程是咖啡店一个员工,他可以选择先做 A 咖啡,在等待搅拌的时候再去做 B 咖啡,提高自己的工作效率。多线程就是咖啡店有多个员工去准备咖啡,但是如果没有协程,那么每个员工在处理咖啡遇到等待的场景时并不会主动去接其他任务。
    supergeek1
        47
    supergeek1  
       87 天前
    @xxfye python 中协程是运行在单线程上的
    shawnsh
        48
    shawnsh  
       87 天前 via Android
    有啥讨论的?拿几本讲操作系统的书认真看看不行吗
    wryyyyyyyyyyyy
        49
    wryyyyyyyyyyyy  
       87 天前
    @Inn0Vat10n 啊? asyncio 不就是协程么,写爬虫、后端都用啊 。后端框架 tornado ,fastapi (我目前只用这两个)都已经支持 async await 了,相关的库有 httpx aiomysql aioredis aiofiles ,可以说我 90%的代码都是协程写的。感觉只要涉及到 io 等长时间阻塞的,都可以用。
    so1n
        50
    so1n  
       87 天前
    @mixuxin go 的也不完全是协程,混合了线程
    inhzus
        51
    inhzus  
       87 天前
    n:1 的协程和 m:n 的协程完全是两回事... 具体问题具体语言具体分析
    so1n
        52
    so1n  
       87 天前
    不说别的语言,单拿 Python 的 Asyncio ,他仍然带有一个线程池,这个线程池可以运行一些 CPU 密集的操作,以及一些系统 API 仍是 Block 的操作:比如文件 IO 和 DNS 。(aiofiles 实际上都是在线程池操作的,只不过都转为了 async await 的形式)
    changz
        53
    changz  
       87 天前
    单用协程你怎么使用多核。。。
    Harumi0720
        54
    Harumi0720  
       87 天前
    @changz Python 目前多线程也用不了多核
    yh7gdiaYW
        55
    yh7gdiaYW  
       87 天前
    @shinonome 至少 python 3.10 下有区别,去年做过对比,在我们项目的场景( CPU 密集型)下,协程比线程还是慢很多
    jiaomeng
        56
    jiaomeng  
       87 天前
    @xxfye 协程也有上下文切换,是因为是在用户态,所以比线程的上下文切换开销小吗
    tyzandhr
        57
    tyzandhr  
       87 天前 via Android
    其实协程才更接近 thread 的语义。fiber 语义也比较接近,不过不够形象。

    线程的话其实翻译为 runner 比较好。
    wushenlun
        58
    wushenlun  
       87 天前
    协程
    A-B-C-A-B-C-A-B-C

    多线程
    ABC-ABC-ABC

    只有 python 才觉得线程鸡肋(没错、就是我)
    kenvix
        59
    kenvix  
       87 天前   ❤️ 1
    @xxfye #23 有人到现在搞不清楚协程和非阻塞的区别,总认为协程=非阻塞,然后搞出“协程适合 io 密集型”这种申必言论。
    协程+阻塞搞 io 密集型照样炸裂
    yinmin
        60
    yinmin  
       87 天前 via iPhone
    最优解是多进程+多协程,跑 python web 时可以用用。
    milkpuff
        61
    milkpuff  
       87 天前
    线程处理回调,协程直接编写完整的请求/处理逻辑,在函数运行中自动挂起和恢复,比写回调体验更好。
    9c04C5dO01Sw5DNL
        62
    9c04C5dO01Sw5DNL  
       87 天前
    当然不是,协程涉及线程上下文切换。而在某些场景下可以通过保持一个/一系列任务始终在同一线程下来避免不必要的线程上下文切换或者锁开销
    ProphetN
        63
    ProphetN  
       86 天前
    应该说有了协程,线程池完全没有意义了。很多业务本身就是自身单线程需求,无需多线程,用协程反而增加开销。
    EndlessMemory
        64
    EndlessMemory  
       85 天前
    协程编程都不方便,同时还得支持协程
    wisej
        65
    wisej  
       85 天前
    @shinonome 在 python 的框架下(有 GIL ),我觉得你说的问题不大。反正 cpu intensive 需要用多进程,io intensive 的协程上下文切换开销小于多线程。

    协程又分有栈协程、无栈协程,后者的理论性能又更高。
    sgld
        66
    sgld  
       84 天前
    @amlee 这是多进程的事吧
    jacktanwhu
        67
    jacktanwhu  
       75 天前
    @dearmymy 求相关的资料?
    Darlewo
        68
    Darlewo  
       74 天前
    @amlee cpu 密集的多线程也不顶用啊
    UN2758
        69
    UN2758  
       73 天前
    可以用的情况,不代表好用,比如你想在已有的 django 项目里实现一个简单多文件上传功能,这种情况你想用协程还是线程池?当你还在考虑哪里 await 和 async for 的时候,我直接 pool.starmap_async 了,协程有时候可用并不代表开发效率能赶上线程
    raviscioniemeche
        70
    raviscioniemeche  
       72 天前
    脱离 python 多线程是可以利用 cpu 多核进行并行任务处理的 而如果单个线程的任务是 io 密集型的 协程依然有很大的用 可以实现时间片的主动让出达到异步的效果
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   955 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 19:46 · PVG 03:46 · LAX 12:46 · JFK 15:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.