Python全局解释锁GIL申请和释放过程
申请GIL
static void take_gil(PyThreadState *tstate)
{
...
// 获取mutex,然后就可以安全地访问GIL了
MUTEX_LOCK(gil->mutex);
// 不断检查GIL状态,一直等到GIL被释放
while (_Py_atomic_load_relaxed(&gil->locked)) {
...
// 等待cond信号,该信号表示拥有GIL的线程已经释放GIL了,等待期间会自动释放mutex
// 成功等到cond信号会返回,否则一直等到超时才返回,返回时会自动重新获取mutex
COND_TIMED_WAIT(gil->cond, gil->mutex, interval, timed_out);
// 如果等待超时,GIL仍然处于锁定状态,并且拥有GIL的线程也没变过
// 那么我们就请求那个线程释放GIL
if (timed_out &&
_Py_atomic_load_relaxed(&gil->locked) &&
gil->switch_number == saved_switchnum)
{
...
// 设置gil_drop_request,请求拥有GIL的线程释放GIL
SET_GIL_DROP_REQUEST(interp);
}
}
// 执行到这里,表示当前线程已经成功获取到了GIL
// 接下来,需要设置GIL的信息
...
// 最后还需要释放mutex,这样就完成了GIL的整个的获取操作
MUTEX_UNLOCK(gil->mutex);
}
释放GIL
static void
drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2,
PyThreadState *tstate)
{
struct _gil_runtime_state *gil = &ceval->gil;
/* tstate is allowed to be NULL (early interpreter init) */
if (tstate != NULL) {
/* Sub-interpreter support: threads might have been switched
under our feet using PyThreadState_Swap(). Fix the GIL last
holder variable so that our heuristics work. */
_Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);
}
MUTEX_LOCK(gil->mutex); // 获取mutex
_Py_ANNOTATE_RWLOCK_RELEASED(&gil->locked, /*is_write=*/1);
_Py_atomic_store_relaxed(&gil->locked, 0); // 释放GIL
COND_SIGNAL(gil->cond); // 通知等待GIL的线程
MUTEX_UNLOCK(gil->mutex); // 释放mutex
}
浙公网安备 33010602011771号