UP | HOME

Python 多线程使用场景

目录

1 前言

当初在学习 Python 多线程的时候就了解到: 由于 GIL 的原因, Python 解释器只允许同一时间执行一个线程。

随着相关基础知识的学习,渐渐明白了这意味着什么,自然而然的,也就思考起了 Python 多线程的应用场景。

2 GIL

全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。

使用多线程的一个目的就是希望通过多个线程的 并发 执行提高程序的执行效率,但是因为 GIL 的原因,使得多线程的 并发性 荡然无存.

全局只允许同一时间执行一个线程意味着: 如果是多线程程序,为了保证各个线程都能完成自身的任务,势必需要进行频繁的 线程切换 操作。

3 线程切换

线程切换 会带来不小的开销,频繁的线程切换会造成资源的浪费。但是在其他环境中,线程可以 并发 的执行,并发带来的效率的提高完全可以忽视因为线程切换带来的消耗。

但是在 Python 中,因为 GIL 的存在,多线程带来的 并发性 不在存在,但线程切换的消耗却没有一点减少。

这似乎意味着,多线程不仅没有带来性能的提升,而且还因为线程切换的原因,使得程序的性能降低了。

多线程编程往往还会提高编码难度,这样一来, Python 中的多线程似乎就失去了存在的价值。

但是,存在即是道理,虽然 Python 多线程存在各种各样的问题,但还是要考虑一种情况引起的线程切换。

4 I/O 操作

曾经,我以为 I/O 操作也是由 CPU 完成的,程序执行 I/O 操作的时候就是 CPU 不断执行神奇的指令从磁盘读写数据。

然后,在学习操作系统的过程中,才发现, I/O 操作是由 磁盘 完成的。

需要执行 I/O 操作的时候, CPU磁盘 发起通知,然后就可以去执行其他东西了。

磁盘 完成相应的 I/O 操作后,向 CPU 发起通知, CPU 在回来继续执行后续的指令。

这也就意味着,当某一个线程等待 I/O 操作完成的时候,可以切换到其他线程完成其他工作。

5 使用场景

到了这里, Python 多线程的使用场景就很明了了。

常规情况下,线程切换是在执行一定数量的指令(3.2 以前)或执行一定时间后(3.2 以后)进行。

这对于 CPU 密集型 的程序来说是不利的,因为 CPU 密集型 的程序主要的消耗集中在执行 CPU 指令上,而 Python 中的多线程因为 GIL 的原因会带来 线程切换 的巨大开销,降低程序性能。

对于 I/O 密集型 的程序,由于 I/O 操作可以交付给 磁盘 完成,此时 GIL 带来的负面影响降到了最低。

因此, Python 多线程适合的使用场景为: I/O 密集型 的应用程序。

对于 CPU 密集型 的程序, 多进程 会带来比 多线程 更好的性能。

6 结语

Python 的多线程适合用在什么地方,晚上早就有很多的讨论了,结论也早已存在。

但是,得出这一结论的思考过程,却是印证所学基础知识的好机会。

多线程和单线程在执行 CPU 密集型I/O 密集型 的比较可以看一看这篇文章:

7 参考链接

版权声明:本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可