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
xiaoshi657
V2EX  ›  Python

大家说一下 多线程 协程 在实际项目中的应用场景

  •  
  •   xiaoshi657 · 2018-05-11 00:16:23 +08:00 · 14440 次点击
    这是一个创建于 2418 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想了解一下实际项目中的应用场景,看教程举的列都是用 time.sleep()模拟的

    24 条回复    2018-05-14 15:32:29 +08:00
    crb912
        1
    crb912  
       2018-05-11 00:27:17 +08:00 via Android   ❤️ 2
    比方说苹果的 heic 图片,里面有 48 个编码的图块。解码时如果逐个(一个个的图块)解也可以,但是多线程并行处理快的多。

    使用多线程并行处理,无非想要提高应用的性能和速度。
    WordTian
        2
    WordTian  
       2018-05-11 00:31:35 +08:00 via Android   ❤️ 1
    比如 web 服务器,一个端口,很多用户同时连接,不用多线程难道让后面的用户等着吗?
    shijingshijing
        3
    shijingshijing  
       2018-05-11 00:34:34 +08:00   ❤️ 1
    我举个简单的例子吧,已知户外有一个温度传感器,这个传感器自带控制器能够 30 秒刷新一次温度值并通过以太网广播出去。订阅这个广播的有很多个用户,比如有一个服务器每收到一次传来的温度值就加上时间戳然后存入数据库中;还有一个户外公告牌用于展示温度值,每次收到以太网的广播数值之后就更新显示。

    现在我在 PC 上设计了一个简单的界面来显示这个数值,UI 本身占了一个线程,该线程负责 UI 的控件显示和刷新;这时候我还需要另外一个线程来监听以太网的广播,这两个线程是不能做到一起的,否则 UI 会挂起失去响应。

    监听广播的线程跑着一个 while ( true )的循环,一旦有更新就触发 event 给 UI 线程进行更新。UI 线程会在收到 event 之后对显示的温度值控件进行更新。
    agagega
        4
    agagega  
       2018-05-11 00:51:22 +08:00   ❤️ 1
    线程:

    1.如果你的 CPU 有多个核,多线程可以利用操作系统的调度机制,让这若干个核同时计算,提高效率。当然多进程的方法也可以利用多核,两者的区别不赘述了。
    2.即使没有两个核,如果你在做一个带用户界面的程序,单线程就意味着你在做某些耗时计算或者 IO 的时候程序界面会卡住。因此分离界面线程和 IO 或计算线程是有利的。
    3.类似地,如果你需要同时处理多个 IO 请求(并发),即使你没有多核,多线程也可以利用操作系统的调度机制,不让计算资源闲置。

    协程:

    你可以去了解一下 JavaScript 的生成器( Generator )。事实上,前面提到的 3 或许根本不是解决并发问题的好方案——如果同时有十万个请求,我们要开十万个线程吗?当然,另一个解决方案是把线程做得轻量化,彻底运行在用户空间,即所谓的 M:N 模型,具体例子就是 Go 语言的 goroutine。
    momocraft
        5
    momocraft  
       2018-05-11 00:54:01 +08:00   ❤️ 3
    一核有難八核圍觀.png
    orangeade
        6
    orangeade  
       2018-05-11 00:59:51 +08:00 via Android   ❤️ 1
    对比下 requests 和 aiohttp,效率的差别
    ericls
        7
    ericls  
       2018-05-11 04:51:42 +08:00 via iPhone
    @agagega 多线程 绕不开 GIL

    多线程可以共享内存
    多进程不共享内存 通过消息传递信息
    Leigg
        8
    Leigg  
       2018-05-11 05:02:31 +08:00 via Android
    python 的 gil 会在程序等待 io 的时候释放,所以 python 的多线程可以提高 io 密集型任务的执行效率,如从一个接口下载 10000 张图片。
    lihongming
        9
    lihongming  
       2018-05-11 07:37:14 +08:00 via Android
    多线程不仅是性能问题,不用多线程的话可能连功能都无法实现。
    比如我做的一个视频监控,每隔 0.03 秒截一张图并识别里面有无目标,有就播放一个嘀嘀嘀的声音提醒监控人员。
    如果没有多线程,那在嘀嘀声播放完以前,是无法继续截图识别的,这就产生了半秒左右的失控期
    araraloren
        10
    araraloren  
       2018-05-11 08:16:36 +08:00
    @crb912 是并发。。。
    lianxiaoyi
        11
    lianxiaoyi  
       2018-05-11 09:03:22 +08:00 via Android
    举个我实际用的案例,我有 10000 多个文件是以压缩包形式存在硬盘,我现在需要把这些文件去进行解压然后将文件内容做一个转换,单线程肯定会慢,那么就可以先把所有文件路径放入 list,启动很多线程,每个线程去 list 中取当前最新文件路径并在 list 中删除当前文件路径,然后去执行相同的任务代码!以前一个人干的事,瞬间变成了 20 个人干甚至更多!大大加快了速度!
    zhujinliang
        12
    zhujinliang  
       2018-05-11 09:06:26 +08:00 via iPhone
    抬个杠…楼上说的某些场景不用多线程也能做…
    比如轮询每个连接、使用状态机处理并发请求,比如 9#的例子我可以严格控制时间,播放音乐时每 0.03 秒检查声卡缓冲区并往声卡缓冲区写足够的数据。
    我觉得多线程好处一个是可以利用多核并行处理能力,另一个是编写、调试直观,执行到哪句就是处理到哪个步骤。状态机的话得先编好状态表,调试得一步步跟状态,脑内模拟状态跳转。
    misaka19000
        13
    misaka19000  
       2018-05-11 09:20:14 +08:00
    @zhujinliang #12 其实最重要的是多线程明显降低了开发者的开发难度,线程是 OS 提供给用户的一套更加强大的 CPU 使用策略;当然 OS 本身还支持多进程,这是为了实现多个程序都能在平台上运行,不过这又是另外一个话题了
    Hopetree
        14
    Hopetree  
       2018-05-11 09:37:54 +08:00
    多线程爬虫,比如,你要爬 100 万个 URL,每个 URL 的请求要耗时 2 秒,如果你用单线程,你要花费的时间是至少 100 万*2,但是我可以用多线程去爬,开 100 个线程啊,100 个线程没人自己去拿 URL,然后去请求,才不要管其他线程有没有结束,最后就是处理请求结果的事情了,那是后话。反正这种耗时的 I/O 密集型就用多线程,可以提高效率
    vicalloy
        15
    vicalloy  
       2018-05-11 10:02:14 +08:00
    很多时候系统瓶颈都在 IO,很多涉及到 IO 特别是网络的程序都需要用到线程 /协程。
    比如你写个 V2EX 的客户端,如果不用多线程,用户点击登录,在请求网络接口的这段时间里界面都会卡死。
    MeteorCat
        16
    MeteorCat  
       2018-05-11 12:48:57 +08:00
    skynet
    muduo
    nonesuccess
        17
    nonesuccess  
       2018-05-11 12:55:44 +08:00 via Android
    记着学操作系统的时候教材里有一句,并行程序的初衷是在单个 cpu 上运行
    neoblackcap
        18
    neoblackcap  
       2018-05-11 16:49:41 +08:00
    这个问题应该是这样看,线程更多是抢占式线程,协程是协作式线程。我们暂时不考虑是有栈还是无栈的区别
    那么协程跟线程的区别更多在于你觉得哪个调度策略更高效。操作系统还是开发者。协程上下文切换现在是在用户空间,因此调度的成本相对较低。不过也不代表这就是高效的。
    我们可以笼统地认为在面对 IO 密集型任务的时候,协程更高效,因为绝大部分时间都是在等待 IO。
    而面对 CPU 密集型的任务,线程更高效

    然而 Python 的常规实现因为有 GIL 的存在,你可以认为协程吊打线程。但是仅在 CPython 跟 PyPy 这些实现里面,千万不要认为是定律

    建议多读读操作系统相关的书记,比如《现代操作系统》,同时了解一下 M:N, 1:1 等线程模型,你会了解到更多
    crb912
        19
    crb912  
       2018-05-11 18:56:42 +08:00 via Android
    @araraloren 抬出去。又一个并发和并行搞不清的ㅍ_ㅍ
    你可以看看这篇文章
    https://blog.csdn.net/Bruce_0712/article/details/65937691
    ycz0926
        20
    ycz0926  
       2018-05-11 19:02:45 +08:00
    还是得看应用呀?
    嵌入式设备上,能简则简,多线程反倒会拉高 cpu,老老实实写几行同步的代码,效率也高
    web 后端,倒是可以试试,不过好像基于协程的项目确实不多,可能是本人孤陋寡闻
    abccba
        21
    abccba  
       2018-05-11 19:12:04 +08:00
    后端服务器用多线程的一个原因是性能。
    服务器都是几十个核,1 个线程只能用 1 个核,多个线程可以充分利用 CPU。进程间通信比线程间复杂,开销也大。
    zjsxwc
        22
    zjsxwc  
       2018-05-11 19:40:58 +08:00
    大部分用于 generator 这个特定场景
    chenqh
        23
    chenqh  
       2018-05-11 23:52:01 +08:00
    感觉现在多线程能不用就不多,特别是脚本语言,没有几个脚本语言线程没有问题,本来线程就复杂,还实现不完整,能用协程就协程
    luzhongqiu
        24
    luzhongqiu  
       2018-05-14 15:32:29 +08:00
    python 中多线程是笑话, 还是乖乖用 asyncio 吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   876 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 21:40 · PVG 05:40 · LAX 13:40 · JFK 16:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.