3.2.6 Python的GIL锁内部机制

GIL(Global Interpreter Lock)全局解释器锁

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

在Cpython中,全局解释器锁,或者叫GIL,是一个互斥体,它可以阻止多个来自执行中的Python字节码的本地线程同时运行。这个锁很重要主要是因为CPython的内存管理在线程上不安全。(不管怎样,由于GIL的存在,其他特性已经越来越依赖于它(指GIL)强制实行的保证)

大概意思就是,python的多线程是假多线程,因为有GIL的存在,同一时间CPU(不管你几个核)只能执行一条线程。这个GIL已经不可能去掉了,因为它已经成为了CPython的基石的一部分,CPython其他很多功能都依赖它才能运行。

上面是英文老师说的,说必须依赖;但下面中文老师又说了,说可以完全不依赖。

首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL。

这里不争论,先继续往下走。

这篇文章透彻的剖析了GIL对python多线程的影响,强烈推荐看一下:http://www.dabeaz.com/python/UnderstandingGIL.pdf 

下面这个示例很好的解释了GIL

import threading
import time

start_time = time.time()
def run(n):
    global num
    time.sleep(0.8)
    num += 1


num = 0
t_l = []    #存放线程
for i in range(10000):
    t = threading.Thread(target=run, args=(‘t-%s‘ % i, ))
    t.start()
    t_l.append(t)    #为了不阻塞其他线程的启动,先放在列表里,最后join

for t in t_l:    #循环线程列表,执行所有线程
    t.join()

print(‘All threads have ran down!‘, threading.current_thread(), threading.activeCount())
time.sleep(0)
#current_thread显示当前线程
#activeCount显示活动的线程数
print(‘Num: ‘, num)
print(‘Total Cost: ‘, time.time() - start_time)

运行结果

All threads have ran down! <_MainThread(MainThread, started 2848)> 1
Num:  10000
Total Cost:  2.0331716537475586

windows下计算正确,但在Ubuntu Linux或MAC OS上可能会出现计算错误的情况。所以,为什么会计算错误呢?看下图

3.2.6 Python的GIL锁内部机制

  1. 全局变量num经过图中前5步的执行,到第5步(由于CPU切换上下文所设定的时间)GIL被强制释放。但此时并未完成num+1,所以num此时还是0。
  2. 6-11步调用num,完成num+1,并赋值给num,释放GIL,此时num=1。
  3. 11-13步调用num,重复之前1-4接13步,这次完成num+1运算,num=2。

亲,我这笔记写的这么好,你看懂了吗?

相关推荐