总结下python中线程调度机制.
对于线程调度机制而言,同操作系统的进程调度一样,最关键是要解决两个问题:
1.在何时选择挂起当前线程,并选择处于等待的先一个线程呢?
2.在众多等待的线程中,选择哪一个作为激活线程呢?
在python多线程机制中,这个两个问题是有两个层次解决的。
如,进程间的切换,当发生了时钟中断,操作系统响应时钟中断,并在这个时候开始进程的调度。 同样的,python也是通过软件模拟了这样的时钟中断,来激激活线程的调度。
我们知道,python字节码解释器是按照指令,顺序一条一条地执行。这就可以在python内部维护一个数值,即就是时钟。如果为N,即当执行了N条指令后,就应该立即启动线程调度机制。
import sys
sys.getcheckinterval()
同时也可以通过sys.setcheckinterval()来调节这个值。
那么接下来,python该在等待的线程中选择哪一个执行呢? 答案是:不知道。 因为python完全没有插手。 由于python是建立在操作系统的原生线程上,所以这样头大的事情就交给操作系统吧。由于不同操作系统的调度机制不一样,故,python提供了一层抽象机制,即 thread(c 实现)以及在其之上的threading(python实现)。 multiprocessing ??
python线程的创建。
通过源码分析,主要完成三个动作:
1.创建并初始化bootstate的结构体 boot,在boot中,将保存关于线程的一切信息,如,线程过程,线程过程的参数。
2.初始化python的多线程环境。(创建GIL)
3.以boot为参数,创建操作系统的原生线程。
特别说明:python启动时,是并不支持多线程的,换句话说,python的多线程的数据结构以及GIL都是没有创建的,这样做,是因为python代码,大部分都不需要多线程的支持。
因为对多线程的支持是有一定代价的:如果激活了多线程机制,而执行的python程序中没有用到多线程,那么在100条指令之后,python虚拟机同样会激活线程的调度。这样就多了一些无用功。
所以,python就把这些留给用户方便、灵活地去控制了。
GIL是什么? 看看源码的主要定义,及其初始化:
typedef struct NRMUTEX {
LONG owned;
DWORD thread_id;
HANDLE hevent;
} NRMUTEX, *PNRMUTEX;
BOOL InitializeNonRecursiveMutex(PNRMUTEX mutex)
{
mutex->owned = -1;
mutex->thread_id = 0
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL)
return mutex->hevent != NULL;// True if the mutex is created