1. 先看一个关于GIL的面试题
描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因。
2. python语言的特征
python语言是解释型语言,执行代码的过程是先将代码交给python解释器,由解释器翻译成机器识别的二进制,然后交给CPU去执行。对于python解释器,有C语言写的称之为cpython,也有java写的称之为Jpython,官方推荐Cpython。
3. GIL
- Python语言和GIL没有半毛钱关系。仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL。
- GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。也就是在处理器是多核的情况下,即使使用了多个线程,也不能利用多核进行并行操作。因为同一时刻只有一个线程执行代码。如果你是两核的CPU,在启动两个形成运行的情况下,每个CPU的使用率只有50%。
- 线程释放GIL锁的情况: 在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100。
- Python使用多进程是可以利用多核的CPU资源的。
- 多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁。
4. 鉴于GIL锁,那么哪些情况适用多线程
我们可以将任务简单分为 计算密集型 和 IO密集型。
对于计算密集型 需要CPU不停的去计算,这个时候不适用适用多线程,即使使用了多线程也不见得有单线程的效率高,因为同一时刻只有一个线程执行。
而对于IO密集型,程序大部分时候都在等待IO操作 输入或者输出,这个时候适用多线程,多个线程的话可以在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,去执行其他代码。如爬去网页的情况,大部分时候程序在等待响应,多线程可以利用等待的时候发送其他请求。
5. 解决GIL锁的办法
1. 更换解释器,如Jpython解释器,不能再GIL锁的问题。
2. 在python中嵌套其他语言实现的多线程代码。