本文章为https://realpython.com/python-gil/该网站的翻译
python的全局解释器锁,一言概之,是一个互斥锁只允许一条线程控制python解释器
这意味着在任何时间 只有一条线程是处于执行状态的 gil锁的影响对于单线程程序来说不太明显 但是它会成为一个性能瓶颈对于python的cpu密集型或者多线程编程
由于Gil锁只允许1条线程在执行即使是在多核cpu上,这一特点使得python语言"臭名昭著"
GIL解决了python的哪些问题?
python在内存管理当中使用了引用计数,这意味着在python当中创建的对象都有个被引用的变量来追踪指向这个对象的引用数。当这个数量变为0时,这个对象占用的内存就释放了。
接下来看一段关于引用计数如何工作的代码:
>>> import sys
>>> a = []
>>> b = a
>>> sys.getrefcount(a)
在上面的例子当中,这个空列表的引用数是3。这个列表对象被a和b引用,并且这个参数被传入了sys.getrefcount方法当中
回到gil:
引用计数需要被保护当多个线程会增/减它的数目时。如果它发生了,它会引发内存泄漏,或者错误的释放一个对象的内存当它还有引用存在时,这会引发crash或者其他奇怪的bug在你的python程序当中。这个引用计数变量可以保证安全当加对在多线程当中共享的数据结构加上锁,这样他们就不会不一致的被更改。
但是通过给1个对象或一组对象加锁会导致另外一个问题-死锁(死锁问题会发生当有超过1个锁存在)。另一个副总用是,当获取锁和释放锁重复性的发生时,性能会下降。
gil是加在python解释器上的锁,执行任何python代码都需要先获得这个解释器锁。这防止了死锁问题(只有一个锁)并且不会引入过多的性能问题,但是它让CPU密集型的python程序“单线程”
gil,即使也被其他语言的解释器所用(比如ruby),不是上面所说问题的唯一解。一些语言避免了使用Gil(作为线程安全当中的内存管理)使用了一些除了引用计数的方法,不如垃圾回收。
从另一个方面来说,那些语言需要去补偿Gil锁单线程带来的性能损失比如通过JIT 编译器。