文档地址:https://docs.python.org/3/c-api/init.html
python解释器不是完全线程安全的。为了支持多线程python程序,有一个全局锁,称为GIL。在当前线程安全访问python对象之前,GIL必须由当前线程持有。没有锁,即使最简单的操作也可能在多线程程序中引起问题:例如,当两个线程同时增加同一个对象的引用次数时,引用次数可能只增加一次,而不是两次。
因此,存在这样一个规则,即只有获得GIL的线程可以操作python对象或调用Python/C API函数。为了模拟并发执行(concurrency of execution),解释器经常尝试切换线程(参见 sys.setswitchinterval())。在读取或写入文件等潜在的阻塞I/O操作时,锁也会释放,以便其他线程可以同时运行。
python解释器在一种被称为PyThreadState的数据结构中,保存了一些具体线程的簿记信息。还有一个全局变量指向当前的PyThreadState,可以通过PyThreadState_Get()来检索它。
文档地址:https://docs.python.org/3/glossary.html#term-global-interpreter-lock
GIL是CPython解释器确保在同一时间只有一个线程执行python字节码的机制。这种机制简化了CPython实现,即使对象(包括关键的内置类型,如dict)隐式安全以防止并发访问(??concurrent access)。锁定整个解释器使其更容易成为多线程的,这是以多处理器提供的并行性为代价的。
然而,一些扩展模型,无论是标准库还是第三方库,都是为了在执行诸如压缩、哈希这样的计算密集型任务时释放GIL而设计的。而且,在执行I/O时GIL总是释放的。
过去,创建一个“free-threaded”解释器(一种以更细粒度锁住共享数据的解释器)的努力没有成功,因为在常见的单处理器情况下性能会受到影响。人们认为,克服这一性能问题会使得实现更复杂,维护成本更高。