大家应该都知道,python有一个GIL(全局解释器锁),用于控制多线程的并发行为。注:GIL不是必须的,可以通过对每个资源单独加锁的方式去掉GIL,也就是将GIL换成更细粒度的锁。
GIL锁的实现
Linux上的POSIX线程的实现有如下行为:
1、同一个线程多次调用pthread_mutex_lock,在linux中默认类型的锁第二次调用总会堵塞
2、一个已经锁住的锁,其他线程调用pthread_mutex_unlock,在linux中默认类型的锁总会被释放
正是由于这些未定义的行为, 并且mutex lock只适用于同步线程对于小段临界区代码的访问,所以GIL的实现没有直接使用原生的pthread_mutex_lock()/pthread_mutex_unlock()
。
GIL的定义
Python的GIL实际是一个<condition, mutex>对, 并用这个条件变量和互斥锁来保护一个locked状态变量
typedef struct {
char locked; /* 0=unlocked, 1=locked */
/* a <cond, mutex> pair to handle an acquire of a locked lock */
pthread_cond_t lock_released;
pthread_mutex_t mut;
} pthread_lock;
可以看出, locked用来指示是否上锁, 1表示已有线程上锁, 0表示锁空闲。
而lock_released和mutex来同步对locked的访问。
从GIL的定义来看,线程对GIL的操作本质上就是通过修改locked状态变量来获取或释放GIL。所以主要的操作有两个: