关于GIL

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

坚持原创技术分享,您的支持将鼓励我继续创作!