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
}

  

posted @ 2022-03-21 22:41  鸪斑兔  阅读(370)  评论(0编辑  收藏  举报