GIL(全局解释器锁)

1、GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。

2、Python和GIL没有半毛钱关系,它是在实现CPython解析器时所引入的一个概念。因为CPython解释器是大部分环境下默认的Python执行环境。由于历史原因,现在非常难以移除。

3、线程释放GIL锁的情况:在IO操作等可能会引起阻塞的 system call 之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL。

4、Python使用多进程是可以利用多核的CPU资源的。

5、爬虫:多线程爬取比单线程爬取,性能有所提升,因为遇到IO阻塞会自动释放GIL锁。

一、测试

在虚拟机中启动linux系统,使用htop命令可看到如下图所示。图中的1、2表示我给当前cpu设置为双核;双核指:同一时刻可以做两件事,且这两件事是互相独立的。

测试代码

01-单线程死循环.py

# 主线程死循环,占满cpu
while True:
    pass

情况1:一个终端运行这份代码。

结果1:运行代码,可以看到单线程任务占满了一个核;结束运行,这个核的占用率立马就降下来了。

情况2:一个终端运行这份代码,在另一个终端再次运行这份代码。

结果2:这两个线程分别占满了这两个核。

02-2个线程死循环.py

import threading

# 子线程死循环
def task():
    while True:
        pass

t = threading.Thread(target=task)
t.start()

# 主线程死循环
while True:
    pass

现象:这两个核的使用率大致都为50%,它们加起来才算真正一个核的资源率。

推测:如果你的程序是多线程,实际上是假的多任务。验证如下:

03-2个进程死循环.py

import multiprocessing

def task():
    while True:
        pass

# 子进程死循环 p = multiprocessing.Process(target=task) p.start() # 主进程死循环 while True: pass

验证得知:在完成一件事情,如果用了多进程、多线程、多协程的这种情况下,真正实现多并发效果的是多进程,多线程可以说是"假"的多并发。为什么这么说呢?因为Cpython解释器的GIL,进程是没有GIL的,线程才有。也就是说,GIL导致程序:你看上去像多并发,实际上是一个在干活,另一个在休息,另一个在干活时,这个又休息了,即只有一个线程在运行。

二、总结

# 计算密集型
    程序系统,大部分时间是CPU在做计算、逻辑判断等,导致cpu占用率很高,而I/O在很短的时间就可以完成
    # 使用 多进程
# I/O密集型
    程序系统,大部分时间是CPU在等I/O,如:频繁网络传输、硬盘/内存读写;I/O密集型的cpu占用率一般不高
    # 使用 线程/协程

 

posted @ 2018-10-05 22:57  就俗人一个  阅读(413)  评论(0编辑  收藏  举报