GIL 全局解释器锁

一. 什么是GIL全局解释器锁

GIL 本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL锁,同一进程内的多个线程必须抢到GIL之后才能使用CPython解释器来执行自己的代码,即同一进程下的多个线程无法实现并行但是可以实现并发

在CPython解释器下,如果想实现并行可以开启多个进程

二. 为何要有GIL

因为CPython解释器的垃圾回收机制不是线程安全的

三. 如何用GIL

有了GIL,应该如何处理并发 :

计算密集型:应该使用多进程
(比如: 一个工厂,需要的是员工没日没夜的工作,那么员工越多工作效率当然就高了)

from multiprocessing import Process
from threading import Thread
import os, time


def work():
    res = 0
    for i in range(100000000):
        res *= i


if __name__ == '__main__':
    l = []
    print(os.cpu_count())
    start = time.time()
    for i in range(4):
        p = Process(target=work)  # 进程 耗时: 5.136266469955444
        # p=Thread(target=work)   # 线程 耗时: 28.20959997177124
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop = time.time()
    print('run time is %s' % (stop - start)) 

IO密集型: 应该开启多线程
(比如: 一个工厂,员工完成了 一个项目的一部分工作 就需要等待原材料运过来,那么减少员工,增加一个员工的项目量(完成一个项目的一部分工作,接着进行下一个项目) ,这样可以在保证效率的前提下,节省开销)

from multiprocessing import Process
from threading import Thread
import threading
import os, time


def work():
    time.sleep(2)


if __name__ == '__main__':
    l = []
    start = time.time()
    for i in range(4):
        # p=Process(target=work) # 进程 耗时: 2.2922799587249756
        p = Thread(target=work)  # 线程 耗时: 2.0377535820007324
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop = time.time()
    print('run time is %s' % (stop - start))

四. GIL vs 自定义互斥锁:

GIL保护的是解释器级的数据,保护用户自己的数据则需要自己加锁处理,如下图:

GIL.png

GIL全局解释器锁并不能保护用户自己的数据,所以说 自定义互斥锁存在是合理的,当我们需要保护自己的数据时可以进行加自定义互斥锁

自定义互斥锁:

from threading import Thread,Lock
import time

mutex=Lock()
n=100
def task():
    global n
    with mutex:
        temp=n
        time.sleep(0.1)
        n=temp-1

if __name__ == '__main__':
    l=[]
    for i in range(100):
        t=Thread(target=task)
        l.append(t)
        t.start()

    for t in l:
        t.join()
    print(n)

推荐阅读更多精彩内容