GIL介绍

在Cpython中,Gloabl Interpreter Lock (GIL) GIL必须被获取,在线程安全访问python对象之前 如果没有GIL, 即使最简单的操作也可能出现问题在多线程程序中,比如两个线程同时增加同一对象的引用计数 引用计数可能只被增加一次,而不是二次 所以,规则就是 只有获取了GIL, 线程才可以操作python对象或者调用python/c api函数 为了模拟并发,解释器通常会进行线程切换,GIL也会被释放当遇到blocking I/O比如读写文件

GIL必要性

所有内存管理方案都依赖以下技术,但是这些与已存在的python/c api不兼容

Tracing 大多数垃圾回收器都需要能够追踪对象的引用地址 cpython自建的指针类型, 比如PyList和PyDict都有tp_traverse方法可以做到,但是不是所有的extention类型都支持该方法

Write barriers 是一些代码,当指针变量被改变后都会执行 无论如何hack Py_INCREF等,你不能执行write barriers 即使可以,方案也需根据栈变量或者全局变量或者对象filed,采用不同的barriers 然而python/c api中没有这些区分

Exact stack information 垃圾回放方案需要能够mark所有的对象通过 local C变量 为了做到,一些方案需要知道变量存储在 c stack 一些python/c api不要求extension可以被track

现有的c extension依赖于GIL 他们假设当extend代码被执行时,其他线程被锁在外面

相关阅读: https://wiki.python.org/moin/GlobalInterpreterLock

https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock

http://python-notes.curiousefficiency.org/en/latest/python3/multicore_python.html

https://softwareengineering.stackexchange.com/questions/186889/why-was-python-written-with-the-gil