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 }