深入理解Python中的GIL(全局解释器锁)GIL是什么?首先来看看GIL究竟是什么。我们需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。GIL全称Global Interpreter Lock,为了防止多线程并发执行机器码,CPython引入了这个全局锁。然而,由于CPython是大部分环境下默认的Python执行环境,许多人将GIL归结为Python语言的缺陷。然而,GIL并不是Python的特性,Python完全可以不依赖于GIL。为什么GIL存在?GIL的问题其实是由于近十几年来应用程序和操作系统逐步从多任务单核心演进到多任务多核心导致的。在一个古老的单核CPU上调度多个线程任务,大家相互共享一个全局锁,谁在CPU执行,谁就占有这把锁。在现代多核心处理器上,原来只能等待的线程任务,现在可以在其它空闲的核心上调度并发执行。由于GIL的存在,如果线程2需要在CPU 2上执行,它需要先等待在CPU 1上执行的线程1释放GIL。如果线程1是因为i/o阻塞让出的GIL,那么线程2必定拿到Gil。但如果线程1是因为timer ticks计数满100让出GIL,那么这个时候线程1和线程2公平竞争。然而,由于Python 2.x中线程1不会动态调整自身的优先级,所以很大概率下次被选中执行的还是线程1,在很多个这样的选举周期内,线程2只能安静的看着线程1拿着GIL在CPU 1上欢快的执行。在Python3中,我们用实际代码来看看GIL的存在对多线程运行的影响。上面这段代码,在Python3上运行,不管是并发执行还是顺序执行,运行时间都差不多,这充分说明了GIL确实会在这种情况下对多线程程序的运行效率产生影响。Python3.6上运行的结果(Python3.2以后对GIL做了较大的优化)Python2.7上运行的结果GIL是否意味着线程安全?有GIL并不意味着python一定是线程安全的。在某些情况下,GIL可以确保线程安全,但在其他情况下,线程安全需要程序员自己处理。例如,当线程A因为进入IO操作而主动释放了GIL时,这种情况下,由于线程A的IO操作等待时间不确定,那么等待的线程B一定会得到GIL锁,这种比较“礼貌的”情况我们一般称为“协同式多任务处理”,相当于大家按照协商好的规则来,线程是安全的,不需要额外加锁。然而,当线程A是因为解释器不间断执行了1000字节码的指令或不间断运行了15毫秒而放弃了GIL时,实际上线程A和线程B将同时竞争GIL锁。在这种情况下,实际上谁会竞争成功是不确定的,所以一般被称为“抢占式多任务处理”。在这种情况下,线程可能就会出现不安全的状态。如何避免GIL的影响?有两个建议:1. 在以IO操作为主的IO密集型应用中,多线程和多进程的性能区别并不大。2. 如果是计算密集型的应用,尽量使用多进程或者协程来代替多线程。