关于多线程是否在Python中工作,我有点困惑.
我知道有很多关于这方面的问题,我已经读了很多,但我仍然感到困惑.我从自己的经验中了解到并且已经看到其他人在StackOverflow上发布他们自己的答案和示例,在Python中确实可以实现多线程.那么为什么每个人都一直说Python被GIL锁定并且一次只能运行一个线程呢?它显然确实有效.或者是否有一些区别我没有到这里?
许多海报/受访者也一直提到线程有限,因为它没有使用多个核心.但我会说它们仍然有用,因为它们可以同时工作,从而更快地完成组合工作量.我的意思是为什么甚至会有一个Python线程模块呢?
更新:
谢谢你到目前为止的所有答案.我理解的方式是多线程只能并行运行某些IO任务,但一次只能运行一个CPU绑定的多个核心任务.
我不完全确定这对我来说在实际意义上是什么意思,所以我只举一个我想要多线程的任务的例子.例如,假设我想遍历很长的字符串列表,我想对每个列表项执行一些基本的字符串操作.如果我拆分列表,将每个子列表发送给我的循环/字符串代码在新线程中处理,并将结果发送回队列,这些工作负载会大致同时运行吗?最重要的是,理论上这会加快运行脚本所需的时间吗?
另一个例子可能是如果我可以在四个不同的线程中使用PIL渲染和保存四个不同的图片,并且这比一个接一个地逐个处理图片更快?我想这个速度组件是我真正想知道的,而不是正确的术语.
我也知道多处理模块,但我现在主要关心的是中小型任务负载(10-30秒),所以我认为多线程会更合适,因为子进程可能很慢启动.
GIL不会阻止线程化.所有GIL都确保一次只有一个线程正在执行Python代码; 控制仍然在线程之间切换.
GIL阻止的是利用多个CPU核心或单独的CPU并行运行线程.
这仅适用于Python代码.C扩展可以并且确实发布GIL以允许多个C代码线程和一个Python线程跨多个内核运行.这扩展到内核控制的I/O,例如select()
调用套接字读取和写入,使Python在多线程多核设置中合理有效地处理网络事件.
然后,许多服务器部署运行多个Python进程,让操作系统处理进程之间的调度,以最大限度地利用CPU内核.如果适合您的用例,您还可以使用该multiprocessing
库来处理来自一个代码库和父进程的多个进程的并行处理.
请注意,GIL仅适用于CPython实现; Jython和IronPython使用不同的线程实现(分别是本机Java VM和.NET公共运行时线程).
直接解决您的更新:任何尝试使用纯Python代码从并行执行中获得速度提升的任务都不会加速,因为线程Python代码被锁定到一次执行的一个线程.但是,如果混合使用C扩展和I/O(例如PIL或numpy操作),并且任何C代码都可以与一个活动的Python线程并行运行.
Python线程非常适合创建响应式GUI,或者用于处理多个短Web请求,其中I/O是比Python代码更多的瓶颈.它不适合并行化计算密集型Python代码,坚持使用multiprocessing
模块执行此类任务或委托给专用外部库.