《Python源码剖析》读书笔记:多线程


 

原始出处: 不沉之月

(如无特别注明,以下笔记都是基于Linux平台)

 

GIL覆盖面不只是Python的解释器,还包括Python的C API

Python线程根据”已执行指令数”来切换线程,在Python 2.5+,这个阈值是100

>>> import sys

>>> sys.getcheckinterval()

100

 

但有些字节码指令执行并不会增加这个计数,因此线程切换时已执行指令数可能会比这个略多

** 当字节码执行之后通过goto转移到fast_next_opcode,这时不会更新计数器

** 线程通过阻塞调度,并不会重置计数器

 

GIL并不是随着解释器启动而创建的,只有用户第一次使用thread的时候创建。

在不同平台上GIL使用不同的实现,在Linux使用信号量。

创建线程使用pthread库,Python线程是使用系统原生线程。

子线程创建后马上申请GIL

PyThreadState保存了这个线程的上下文信息

当一个活动线程挂起后,调度到哪个线程由操作系统线程调度决定。当前活动线程挂起前,会释放GIL

 

Python线程调度有两种方式,一种是标准调度,另一种是阻塞调度。

** 标准调度是当前线程已执行指令数大于100时主动释放GIL,让其他线程有机会运行。

** 阻塞调度是当前线程执行到阻塞的系统调用(例如time.sleep)之前,释放GIL,让其他线程有机会运行。

 

thread模块提供基础的Lock对象,默认使用信号量,如果在信号量有问题的情况下,使用pthread_lock

 

当前线程对Lock对象加锁前,先释放GIL,获得锁后再获取GIL。(Threadmodule.c:38)

threading模块是Python写成的。里面的RLock/Condition/Semaphore/Event锁对象都是基于thread.Lock

threading模块的Thread启动分两步,第一步使用thread.start_new_thread创建原生线程,原生线程执行__bootstrap函数,此时线程状态为创建中,放入_limbo字典;第二步在__bootstrap函数中将自己放到_active字典,以线程ID为key,、然后执行run函数

PS: 求购正版《Python源码剖析》,或求提供陈儒联系方式,谢谢!

相关内容

    暂无相关文章

评论关闭