Python48_GIL的问题

2019-09-28  本文已影响0人  jxvl假装

GIL:全局解释器锁
作用:保证了多个线程时,在同一时刻只有一个线程会被调用(不管电脑是几核的)(也就是说python中的线程其实是假的,这就造成在python中多进程的效率远远高于多线程,特别是多核的时候)

因此,在python中,能用进程的时候尽量用进程,而不使用线程

如果非要用线程呢?如何解决?
关键的地方用C语言来写

用死循环进行示例,通过查看各个核的占用情况(Linux中可以用htop)查看是否实现了真正的多线程

用C语言在loop.c文件中写一个死循环

void DeadLoop()
{
    while(1)
    {
    ;
    }
}

并将之做成一个库
(Linux环境中)
gcc loop.c -shared -o libdeadloop.so
就会生成一个libdeadloop.so的文件(动态库)

在python文件中

from ctypes import *
from threading import Thread

#加载动态库
lib = cdl.LoadLibrary("./libdeadloop.so")   #假设做制作的动态库就在当前目录下
#cdl是ctypes里面的

#创建一个子线程,让其执行C语言编写不函数,此函数是一个死循环
t = Thread(target=lib.DeadLoop) #DeadLoop是动态库里面的函数(即上面用C语言编写的函数的函数名)
t.start()

while True:
    pass
#会发现两个核的占用很快就达到很高的占用

面试题

描述Ptyhon GIL的概念,以及它对python多线程的影响?多线程爬取程序是否可以比单线程快?并解释原因

参考答案:

  1. GIL并不是Python语言的问题,仅仅是由于历史原因在Cpython解释器(Python官网推荐)中难以移除GIL(比如java语言写的jpython就没有这个问题)。
  2. GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码
  3. 线程释放GIL锁的情况:在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL。Python 3.x使用计时器(执行时间大到阀值后,当前线程释放GIL)或Python 2.x,tickets达到100
  4. Python使用多进程是可以利用多核的CPU资源的
  5. 多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁

如何避免GIL的问题?

  1. 避免使用Cpython解释器
  2. 用其他语言替代线程中要做的事情

GIL主要是对于计算密集型不利,对于IO密集型,用多线程(或协程)仍然能够提升性能

上一篇 下一篇

猜你喜欢

热点阅读