当从 C(或 C++)线程调用 Python 代码时,我对如何确保线程安全感到非常困惑。
Python 文档似乎在说这样做的惯用语是:
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
/* Perform Python actions here. */
result = CallSomeFunction();
/* evaluate result or handle exception */
/* Release the thread. No Python API allowed beyond this point. */
PyGILState_Release(gstate);
事实上,这个stackoverflow 的答案似乎也证实了这一点。但是一位评论者(享有很高的声誉)却说不然。评论者说你应该使用PyEval_RestoreThread()
/ PyEval_SaveThread()
。
文档似乎证实了这一点:
PyThreadState* PyEval_SaveThread()
Release the global interpreter lock (if it has been created and
thread support is enabled) and reset the thread state to NULL,
returning the previous thread state (which is not NULL). If the lock
has been created, the current thread must have acquired it. (This
function is available even when thread support is disabled at compile
time.)
void PyEval_RestoreThread(PyThreadState *tstate)
Acquire the global interpreter lock (if it has been created and thread
support is enabled) and set the thread state to tstate, which must not
be NULL. If the lock has been created, the current thread must not have
acquired it, otherwise deadlock ensues. (This function is available even
when thread support is disabled at compile time.)
文档描述这一点的方式,似乎PyEval_RestoreThread()
/PyEval_SaveThread()
基本上是一个互斥锁/解锁习语。因此,在从 C 调用任何 Python 代码之前,您首先需要锁定 GIL,然后再解锁它,这是有道理的。
那么它是哪一个?从 C 调用 Python 代码时,我应该使用:
PyGILState_Ensure()/PyGILState_Release()
或者
PyEval_RestoreThread/PyEval_SaveThread
?
真正的区别是什么?