线程状态和全局解释器锁

除非使用 CPythonfree-threaded build 版本,否则Python 解释器通常都不是线程安全的。 为了支持多线程的 Python 程序,解释器有一个全局锁,称为 global interpreter lockGIL,线程必须在访问 Python 对象之前先持有它。 如果没有这个锁,即使最简单的操作在多线程的程序中也可能造成问题:例如,当两个线程同时递增同一个对象的引用计数时,引用计数可能只增加一次而不是两次。

因此,线程必须持有 GIL 才能操作 Python 对象或唤起 Python 的 C API。

为了模拟并发,解释器会定期在字节指令间尝试切换线程 (参见 sys.setswitchinterval())。 因此在纯 Python 代码中也必须要有这个锁。

此外,全局解释器锁会在阻塞型 I/O 操作时被释放,如读取或写入文件等。 在 C API 中,这是通过 分离线程状态 完成的。

Python 解释器会将线程的局部信息保存在名为 PyThreadState 的数据结构中,或称 thread state。 每个线程都有一个指向 PyThreadState 的线程局部指针;这个指针所引用的线程状态会被视为 已附加线程状态

一个线程在同一时刻只能拥有一个 attached thread state。 已附加线程状态通常等同于持有 GIL,但在自由线程构建中例外。 在启用 GIL 的构建中,附加线程状态会阻塞执行直到 GIL 可以被获取。 不过,即使在禁用 GIL 的构建中,仍然需要拥有已附加线程状态,因为解释器需要记住有哪些线程可以访问 Python 对象。

备注

即使在自由线程构建中,附加线程状态也可能发生阻塞,因为 GIL 可以被重新启用或者线程可能被临时挂起(例如在垃圾回收期间)。

通常,在使用 Python 的 C API 时总是会存在一个已附加线程状态,包括执行嵌入期间和实现方法时,因此你很少会需要自行设置线程状态。 仅在某些特定情况下,例如处于某个 Py_BEGIN_ALLOW_THREADS 代码块或全新线程中,线程才没有已附加线程状态。 如果不确定,可检查 PyThreadState_GetUnchecked() 是否返回 NULL

If it turns out that you do need to create a thread state, it is recommended to use PyThreadState_Ensure() or PyThreadState_EnsureFromView(), which will manage the thread state for you.

从扩展代码分离线程状态

大多数操作 thread state 的扩展代码具有以下简单结构:

Save the thread state in a local variable.
... Do some blocking I/O operation ...
Restore the thread state from the local variable.

这是如此常用因此增加了一对宏来简化它:

Py_BEGIN_ALLOW_THREADS
... 执行某些阻塞式的 I/O 操作 ...
Py_END_ALLOW_THREADS

Py_BEGIN_ALLOW_THREADS 宏将打开一个新块并声明一个隐藏的局部变量;Py_END_ALLOW_THREADS 宏将关闭这个块。

上面的代码块可扩展为下面的代码:

PyThreadState *_save;

_save = PyEval_SaveThread();
... 执行某些阻塞式的 I/O 操作 ...
PyEval_RestoreThread(_save);

下面介绍这些函数是如何运作的:

附加线程状态意味着为解释器持有 GIL。 要将其分离,则调用 PyEval_SaveThread() 并将结果保存在局部变量中。

通过分离线程状态,GIL 将被释放,以允许其他线程附加到该解释器并执行而让当前线程执行阻塞式 I/O。 当 I/O 操作完成时,可通过调用 PyEval_RestoreThread() 重新附加旧线程状态,该函数将等待至 GIL 可被获取。

备注

执行阻塞型 I/O 操作是分离线程状态最常见的使用场景,但它也适用于不需要访问 Python 对象或 Python 的 C API 的长时间运行的原生代码。 例如,标准库 zlibhashlib 模块会在对数据执行压缩或哈希运算时分离 线程状态

free-threaded build 中,通常不需要考虑 GIL,但是 分离线程状态仍然是需要的,因为解释器需要定期地阻塞所有线程以获取稳定的 Python 对象视图而不会产生竞争条件风险。 例如,CPython 目前会在运行垃圾回收器的时候暂时挂起所有线程。

警告

在解释器最终化期间分离线程状态可能导致非预期的行为。 请参阅 Cautions regarding interpreter finalization 了解详情。

API

以下的宏被使用时通常不带末尾分号;请在 Python 源代码发布包中查看示例用法。

备注

这些宏对于在 free-threaded build 上防止死锁仍然是必要的。

Py_BEGIN_ALLOW_THREADS
属于 稳定 ABI.

此宏会扩展为 { PyThreadState *_save; _save = PyEval_SaveThread();。 请注意它包含一个开头花括号;它必须与后面的 Py_END_ALLOW_THREADS 宏匹配。有关此宏的进一步讨论请参阅上文。

Py_END_ALLOW_THREADS
属于 稳定 ABI.

此宏扩展为 PyEval_RestoreThread(_save); }。注意它包含一个右花括号;它必须与之前的 Py_BEGIN_ALLOW_THREADS 宏匹配。请参阅上文以进一步讨论此宏。

Py_BLOCK_THREADS
属于 稳定 ABI.

这个宏扩展为 PyEval_RestoreThread(_save);: 它等价于没有关闭花括号的 Py_END_ALLOW_THREADS 宏。

Py_UNBLOCK_THREADS
属于 稳定 ABI.

这个宏扩展为 _save = PyEval_SaveThread();: 它等价于没有开始花括号和变量声明的 Py_BEGIN_ALLOW_THREADS 宏。

Using the C API from foreign threads

当使用专门的 Python API(如 threading 模块)创建线程时,会自动为其关联一个附加线程状态,不过,当线程是从原生代码创建时(例如,由具有自己的线程管理的第三方库创建),它就不会持有附加线程状态。

如果你需要从这些线程调用 Python 代码(这常常会是前述第三方库提供的回调 API 的一部分),你必须先通过新建一个线程状态并附加它来向解释器注册这些线程。

The easiest way to do this is through PyThreadState_Ensure() or PyThreadState_EnsureFromView().

备注

These functions require an argument pointing to the desired interpreter; such a pointer can be acquired via a call to PyInterpreterGuard_FromCurrent() (for PyThreadState_Ensure) or PyInterpreterView_FromCurrent() (for PyThreadState_EnsureFromView) from the function that creates the thread. If no pointer is available (such as when the given native thread library doesn't provide a data argument), PyInterpreterView_FromMain() can be used to get a view for the main interpreter, but note that this will make the code incompatible with subinterpreters.

例如:

// The return value of PyInterpreterGuard_FromCurrent() from the
// function that created this thread.
PyInterpreterGuard *guard = thread_data->guard;

// Create a new thread state for the interpreter.
PyThreadStateToken *token = PyThreadState_Ensure(guard);
if (token == NULL) {
   PyInterpreterGuard_Close(guard);
   return;
}

// We have a valid thread state -- perform Python actions here.
result = CallSomeFunction();
// Evaluate result or handle exceptions.

// Release the thread state. No calls to the C API are allowed beyond this
// point.
PyThreadState_Release(token);
PyInterpreterGuard_Close(guard);

Keep in mind that calling PyThreadState_Ensure might not always create a new thread state, and calling PyThreadState_Release might not always detach it. These functions may reuse an existing attached thread state, or may re-attach a thread state that was previously attached for the current thread.

参见

PEP 788

Attaching/detaching thread states

PyThreadStateToken *PyThreadState_Ensure(PyInterpreterGuard *guard)
属于 稳定 ABI 自 3.15 版起.

Ensure that the thread has an attached thread state for the interpreter protected by guard, and thus can safely invoke that interpreter.

It is OK to call this function if the thread already has an attached thread state, as long as there is a subsequent call to PyThreadState_Release() that matches this one (meaning that "nested" calls to this function are permitted).

The function's effect (if any) will be reversed by the matching call to PyThreadState_Release().

On error, this function returns NULL without an exception set. Do not call PyThreadState_Release() in this case.

On success, this function returns a pointer value that must be passed to the matching call to PyThreadState_Release().

The conditions in which this function creates a new thread state are considered unstable and implementation-dependent. If you need to control the exact lifetime of a thread state, consider using PyThreadState_New(). However, do not avoid this function solely on the basis that the lifetime of the thread state may be inconsistent across versions; changes to this function will be done with caution and in a backwards-compatible manner. In particular, the saving of thread-local variables and similar state will be retained across Python versions.

CPython 实现细节: The exact behavior of whether this function creates a new thread state is described below, but be aware that this may change in the future.

First, this function checks if an attached thread state is present. If there is, this function then checks if the interpreter of that thread state matches the interpreter guarded by guard. If that is the case, this function simply marks the thread state as being used by a PyThreadState_Ensure call and returns.

If there is no attached thread state, then this function checks if any thread state has been used by the current OS thread. (This is returned by PyGILState_GetThisThreadState().) If there was, then this function checks if that thread state's interpreter matches guard. If it does, it is re-attached and marked as used.

Otherwise, if both of the above cases fail, a new thread state is created for guard. It is then attached and marked as owned by PyThreadState_Ensure.

Added in version 3.15.

PyThreadStateToken *PyThreadState_EnsureFromView(PyInterpreterView *view)
属于 稳定 ABI 自 3.15 版起.

Get an attached thread state for the interpreter referenced by view.

The behavior and return value are the same as for PyThreadState_Ensure(); additionally, if the function succeeds, the interpreter referenced by view will be implicitly guarded. The guard will be released upon the corresponding PyThreadState_Release() call.

Added in version 3.15.

void PyThreadState_Release(PyThreadStateToken *token)
属于 稳定 ABI 自 3.15 版起.

Undo a PyThreadState_Ensure() or PyThreadState_EnsureFromView() call.

This must be called exactly once for each successful Ensure call, with token set to that call's return value.

The state that was attached before the corresponding Ensure call (if any) will be attached when PyThreadState_Release() returns.

The exact behavior of whether this function deletes a thread state is considered unstable and implementation-dependent.

CPython 实现细节: Currently, this function will decrement an internal counter on the attached thread state. If this counter ever reaches below zero, this function emits a fatal error (via Py_FatalError()).

If the attached thread state is owned by PyThreadState_Ensure, then the attached thread state will be deallocated and deleted upon the internal counter reaching zero. Otherwise, nothing happens when the counter reaches zero.

Added in version 3.15.

type PyThreadStateToken
属于 稳定 ABI (作为不透明的结构体) 自 3.15 版起.

An opaque token retrieved from a PyThreadState_Ensure() call and passed to a corresponding PyThreadState_Release() call.

GIL 状态 API

The following APIs are generally not compatible with subinterpreters and will hang the process during interpreter finalization (see Cautions regarding interpreter finalization). As such, these APIs were soft deprecated in Python 3.15 in favor of the new APIs.

type PyGILState_STATE
属于 稳定 ABI.

PyGILState_Ensure() 返回并传递给 PyGILState_Release() 的值的类型。

enumerator PyGILState_LOCKED

当调用 PyGILState_Ensure() 时 GIL 已经被持有。

enumerator PyGILState_UNLOCKED

当调用 PyGILState_Ensure() 时 GIL 尚未被持有。

PyGILState_STATE PyGILState_Ensure()
属于 稳定 ABI.

确保当前线程可以调用 Python C API,无论 Python 的当前状态或 attached thread state 如何。只要每个调用都与对 PyGILState_Release() 的调用相匹配,线程就可以根据需要多次调用此函数。通常,只要线程状态在调用 Release() 之前恢复到其先前状态,就可以在 PyGILState_Ensure()PyGILState_Release() 调用之间使用其他与线程相关的 API。例如,可以正常使用 Py_BEGIN_ALLOW_THREADSPy_END_ALLOW_THREADS 宏。

返回值是一个不透明的"句柄",指向调用 PyGILState_Ensure() 时的 attached thread state,必须将其传递给 PyGILState_Release() 以确保 Python 恢复到相同状态。尽管允许递归调用,但这些句柄 不能 共享 — 每次对 PyGILState_Ensure() 的独立调用都必须保存其对应的句柄,用于后续调用 PyGILState_Release()

When the function returns, there will be an attached thread state and the thread will be able to call arbitrary Python code.

This function has no way to return an error. As such, errors are either fatal (that is, they send SIGABRT and crash the process; see Py_FatalError()), or the thread will be permanently blocked (such as during interpreter finalization).

警告

Calling this function when the interpreter is finalizing will infinitely hang the thread, which may cause deadlocks. Cautions regarding interpreter finalization for more details.

In addition, this function generally does not work with subinterpreters when used from foreign threads, because this function has no way of knowing which interpreter created the thread (and as such, will implicitly pick the main interpreter).

在 3.14 版本发生变更: 如果在解释器处于终结阶段时调用此函数,当前线程将被挂起而非终止。

自 3.15 版起已处于 Soft deprecated 状态: Use PyThreadState_Ensure() or PyThreadState_EnsureFromView() instead.

void PyGILState_Release(PyGILState_STATE)
属于 稳定 ABI.

Release any resources previously acquired. After this call, Python's state will be the same as it was prior to the corresponding PyGILState_Ensure() call (but generally this state will be unknown to the caller, hence the use of the GIL-state API).

PyGILState_Ensure() 的每次调用都必须与在同一线程上对 PyGILState_Release() 的调用相匹配。

自 3.15 版起已处于 Soft deprecated 状态: Use PyThreadState_Release() instead.

PyThreadState *PyGILState_GetThisThreadState()
属于 稳定 ABI.

Get the thread state that was most recently attached for this thread. (If the most recent thread state has been deleted, this returns NULL.)

If the caller has an attached thread state, it is returned.

In other terms, this function returns the thread state that will be used by PyGILState_Ensure(). If this returns NULL, then PyGILState_Ensure will create a new thread state.

This function cannot fail.

自 3.15 版起已处于 Soft deprecated 状态: Use PyThreadState_Get() or PyThreadState_GetUnchecked() instead.

int PyGILState_Check()

Return 1 if the current thread has an attached thread state that matches the thread state returned by PyGILState_GetThisThreadState(). If the caller has no attached thread state or it otherwise doesn't match, then this returns 0.

If the current Python process has ever created a subinterpreter, this function will always return 1.

This is mainly a helper/diagnostic function.

Added in version 3.4.

自 3.15 版起已处于 Soft deprecated 状态: Use PyThreadState_GetUnchecked() != NULL instead.

有关 fork() 的注意事项

有关线程的另一个需要注意的重要问题是它们在面对 C fork() 调用时的行为。在大多数支持 fork() 的系统中,当一个进程执行 fork 之后将只有发出 fork 的线程存在。这对需要如何处理锁以及 CPython 的运行时内所有的存储状态都会有实质性的影响。

只保留“当前”线程这一事实意味着任何由其他线程所持有的锁永远不会被释放。Python 通过在 fork 之前获取内部使用的锁,并随后释放它们的方式为 os.fork() 解决了这个问题。此外,它还会重置子进程中的任何 Lock 对象。在扩展或嵌入 Python 时,没有办法通知 Python 在 fork 之前或之后需要获取或重置的附加(非 Python)锁。需要使用 OS 工具例如 pthread_atfork() 来完成同样的事情。此外,在扩展或嵌入 Python 时,直接调用 fork() 而不是通过 os.fork() (并返回到或调用至 Python 中) 调用可能会导致某个被 fork 之后失效的线程所持有的 Python 内部锁发生死锁。 PyOS_AfterFork_Child() 会尝试重置必要的锁,但并不总是能够做到。

所有其他线程都将结束这一事实也意味着 CPython 的运行时状态必须妥善清理,os.fork() 就是这样做的。 这意味着最终化归属于当前解释器的所有其他 PyThreadState 对象以及所有其他 PyInterpreterState 对象。由于这一点以及 "main" 解释器 的特殊性质,fork() 应当只在该解释器 的 "main" 线程中被调用,而 CPython 全局运行时最初就是在该线程中初始化的。只有当 exec() 将随后立即被调用的情况是唯一的例外。

高层级 API

这些是在编写多线程 C 扩展时最常用的类型和函数。

type PyThreadState
属于 稳定 ABI (作为不透明的结构体).

该数据结构代表单个线程的状态。唯一的公有数据成员为:

PyInterpreterState *interp

该线程的解释器状态。

void PyEval_InitThreads()
属于 稳定 ABI.

不执行任何操作的已弃用函数。

在 Python 3.6 及更老的版本中,此函数会在 GIL 不存在时创建它。

在 3.9 版本发生变更: 此函数现在不执行任何操作。

在 3.7 版本发生变更: 该函数现在由 Py_Initialize() 调用,因此你无需再自行调用它。

在 3.2 版本发生变更: 此函数已不再被允许在 Py_Initialize() 之前调用。

自 3.9 版本弃用.

PyThreadState *PyEval_SaveThread()
属于 稳定 ABI.

分离当前线程的 attached thread state 并返回该状态对象。调用此函数返回后,当前线程将不再关联任何 thread state 线程状态。

void PyEval_RestoreThread(PyThreadState *tstate)
属于 稳定 ABI.

attached thread state 设置为 tstate。传入的 thread state 不应 处于 已附加 状态,否则会导致死锁。调用此函数返回后,tstate 将被附加到当前线程。

备注

当运行时处于终结阶段时,若从某个线程调用此函数,该线程将被挂起直至程序退出,即便是由非 Python 创建的线程也不例外。更多详情请参考 Cautions regarding interpreter finalization 小节。

在 3.14 版本发生变更: 如果在解释器处于终结阶段时调用此函数,当前线程将被挂起而非终止。

PyThreadState *PyThreadState_Get()
属于 稳定 ABI.

返回当前线程的 attached thread state。如果线程没有已附加的线程状态(例如,当处于 Py_BEGIN_ALLOW_THREADS 代码块内部时),则会触发致命错误 (因此调用者无需检查返回值是否为 NULL 值)。

另请参阅 PyThreadState_GetUnchecked()

PyThreadState *PyThreadState_GetUnchecked()

PyThreadState_Get() 类似,但如果其为 NULL 则不会杀死进程并设置致命错误。调用方要负责检查结果是否为 NULL 值。

Added in version 3.13: 在 Python 3.5 到 3.12 中,此函数是私有的并且命名为 _PyThreadState_UncheckedGet()

PyThreadState *PyThreadState_Swap(PyThreadState *tstate)
属于 稳定 ABI.

attached thread state 设置为 tstate,并返回调用此函数前已附加的 thread state 线程状态。

此函数在没有 attached thread state 的情况下调用也是安全的;此时它会直接返回 NULL,表示之前不存在线程状态。

备注

PyGILState_Ensure() 类似,当运行时处于终结阶段时,调用此函数会导致线程挂起。

低层级 API

PyThreadState *PyThreadState_New(PyInterpreterState *interp)
属于 稳定 ABI.

创建一个属于指定解释器对象的新线程状态对象。此操作不需要存在 attached thread state

void PyThreadState_Clear(PyThreadState *tstate)
属于 稳定 ABI.

重置 thread state 对象中的所有信息。 tstate 必须处于 已附加 状态。

在 3.9 版本发生变更: 此函数现在会调用 PyThreadState.on_delete 回调。在之前版本中,此操作是发生在 PyThreadState_Delete() 中的。

在 3.13 版本发生变更: PyThreadState.on_delete 回调已被移除。

void PyThreadState_Delete(PyThreadState *tstate)
属于 稳定 ABI.

销毁一个 thread state 对象。tstate 不应被 已附加 到任何线程。tstate 必须在之前通过调用 PyThreadState_Clear() 进行过重置。

void PyThreadState_DeleteCurrent(void)

分离 attached thread state (该状态必须已通过先前调用 PyThreadState_Clear() 进行重置),然后销毁它。

返回时将不会有任何 thread state 处于 已附加 状态。

PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate)
属于 稳定 ABI 自 3.10 版起.

获取 Python 线程状态 tstate 的当前帧。

返回一个 strong reference。如果没有当前执行的帧则返回 NULL

另请参阅 PyEval_GetFrame()

tstate 不得为 NULL,并且必须处于 已附加 状态。

Added in version 3.9.

uint64_t PyThreadState_GetID(PyThreadState *tstate)
属于 稳定 ABI 自 3.10 版起.

获取 Python 线程状态 tstate 的唯一 thread state 标识符。

tstate 不得为 NULL,并且必须处于 已附加 状态。

Added in version 3.9.

PyInterpreterState *PyThreadState_GetInterpreter(PyThreadState *tstate)
属于 稳定 ABI 自 3.10 版起.

获取 Python 线程状态 tstate 对应的解释器。

tstate 不得为 NULL,并且必须处于 已附加 状态。

Added in version 3.9.

void PyThreadState_EnterTracing(PyThreadState *tstate)

暂停 Python 线程状态 tstate 中的追踪和性能分析。

使用 PyThreadState_LeaveTracing() 函数来恢复它们。

Added in version 3.11.

void PyThreadState_LeaveTracing(PyThreadState *tstate)

恢复 Python 线程状态 tstate 中被 PyThreadState_EnterTracing() 函数暂停的追踪和性能分析。

另请参阅 PyEval_SetTrace()PyEval_SetProfile() 函数。

Added in version 3.11.

int PyUnstable_ThreadState_SetStackProtection(PyThreadState *tstate, void *stack_start_addr, size_t stack_size)
这是 不稳定 API。它可能在次要版本中不经警告地被更改。

设置一个 Python 线程状态的栈保护起始地址和栈保护大小。

成功时,返回 0。失败时,设置一个异常并返回 -1

CPython 通过在注意到机器的执行栈即将溢出时引发 RecursionError 实现针对 C 代码的 递归控制。请查看 Py_EnterRecursiveCall() 函数的示例。为此,需要知道当前线程栈的位置,这通常是从操作系统获取的。例如当使用 Boost 库的 boost::context 之类的上下文切换技术使栈发生改变时,你必须调用 PyUnstable_ThreadState_SetStackProtection() 将变化通知给 CPython。

在修改栈之前或之后调用 PyUnstable_ThreadState_SetStackProtection()。 不要在调用和栈修改之间调用任何其他 Python C API。

请参阅 PyUnstable_ThreadState_ResetStackProtection() 了解如何撤销此操作。

Added in version 3.15.

void PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate)
这是 不稳定 API。它可能在次要版本中不经警告地被更改。

将一个 Python 线程状态的栈保护起始地址和栈保护大小重置为操作系统的默认值。

请参阅 PyUnstable_ThreadState_SetStackProtection() 查看相关说明。

Added in version 3.15.

PyObject *PyThreadState_GetDict()
返回值:借入的引用。 属于 稳定 ABI.

返回一个字典,扩展模块可在其中存储线程特定的状态信息。每个扩展模块应使用唯一的键来在此字典中存储状态。当没有 thread state 处于 已附加 状态时,调用此函数是安全的。如果此函数返回 NULL,则表示没有引发异常,调用者应假定没有线程状态被附加。

void PyEval_AcquireThread(PyThreadState *tstate)
属于 稳定 ABI.

tstate 附加 到当前线程,当前线程不能为 NULL 或者已经 附加线程状态

调用方线程不能已经具有 attached thread state

备注

当运行时处于终结阶段时,若从某个线程调用此函数,该线程将被挂起直至程序退出,即便是由非 Python 创建的线程也不例外。更多详情请参考 Cautions regarding interpreter finalization 小节。

在 3.8 版本发生变更: 已被更新为与 PyEval_RestoreThread(), Py_END_ALLOW_THREADS()PyGILState_Ensure() 保持一致,如果在解释器正在最终化时被调用则会终结当前线程。

在 3.14 版本发生变更: 如果在解释器处于终结阶段时调用此函数,当前线程将被挂起而非终止。

PyEval_RestoreThread() 是一个始终可用的(即使线程尚未初始化)更高层级函数。

void PyEval_ReleaseThread(PyThreadState *tstate)
属于 稳定 ABI.

分离 attached thread statetstate 参数必须不为 NULL,该参数仅被用于检查它是否代表 attached thread state --- 如果不是,则会报告一个致命级错误。

PyEval_SaveThread() 是一个始终可用的(即使线程尚未初始化)更高层级函数。

异步通知

提供了一种向主解释器线程发送异步通知的机制。这些通知将采用函数指针和空指针参数的形式。

int Py_AddPendingCall(int (*func)(void*), void *arg)
属于 稳定 ABI.

将一个函数加入从主解释器线程调用的计划任务。成功时,将返回 0 并将 func 加入要被主线程调用的等待队列。失败时,将返回 -1 但不会设置任何异常。

当成功加入队列后,func最终 附带参数 arg 被主解释器线程调用。对于正常运行的 Python 代码来说它将被异步地调用,但要同时满足以下两个条件:

func 必须在成功时返回 0,或在失败时返回 -1 并设置一个异常。 func 不会被中断来递归地执行另一个异步通知,但如果 thread state 已被分离则它仍可被中断以切换线程。

此函数不需要 attached thread state。不过,要在子解释器中调用此函数,调用方必须具有 attached thread state。否则,函数 func 可能会被安排给错误的解释器来调用。

警告

This is a low-level function, only useful for very special cases. There is no guarantee that func will be called as quick as possible. If the main thread is busy executing a system call, func won't be called before the system call returns. This function is generally not suitable for calling Python code from arbitrary C threads. Instead, use PyThreadState_EnsureFromView().

Added in version 3.1.

在 3.9 版本发生变更: 如果此函数在子解释器中被调用,则函数 func 将被安排在子解释器中调用,而不是在主解释器中调用。现在每个子解释器都有自己的计划调用列表。

在 3.12 版本发生变更: 此函数现在总是会安排 func 在主解释器中运行。

int Py_MakePendingCalls(void)
属于 稳定 ABI.

执行所有待命的调用。这通常会由解释器自动执行。

此函数成功时返回 0,失败时返回 -1 并设置一个异常。

如果此函数不是在主解释器的主线程中被调用,它将不做任何事并返回 0。调用方必须持有 attached thread state 线程状态。

Added in version 3.1.

在 3.12 版本发生变更: 此函数将只在主解释器中运行待命的调用。

int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
属于 稳定 ABI.

Schedule an exception to be raised asynchronously in a thread. If the thread has a previously scheduled exception, it is overwritten.

The id argument is the thread id of the target thread, as returned by PyThread_get_thread_ident(). exc is the class of the exception to be raised, or NULL to clear the pending exception (if any).

Return the number of affected thread states. This is normally 1 if id is found, even when no change was made (the given exc was already pending, or exc is NULL but no exception is pending). If the thread id isn't found, return 0. This raises no exceptions.

To prevent naive misuse, you must write your own C extension to call this. This function must be called with an attached thread state. This function does not steal any references to exc. This function does not necessarily interrupt system calls such as sleep().

在 3.7 版本发生变更: id 形参的类型已从 long 变为 unsigned long

操作系统线程 API

PYTHREAD_INVALID_THREAD_ID

代表无效线程 ID 的哨兵值。

该值目前等于 (unsigned long)-1

unsigned long PyThread_start_new_thread(void (*func)(void*), void *arg)
属于 稳定 ABI.

在新线程中启动函数 func 并传入参数 arg。结果线程将不被合并。

func 不可为 NULL,但 arg 可以为 NULL

成功时,此函数将返回新线程的标识号;失败时,将返回 PYTHREAD_INVALID_THREAD_ID

调用方不需要持有 attached thread state

unsigned long PyThread_get_thread_ident(void)
属于 稳定 ABI.

返回当前线程的标识号,它一定不为零。

此函数不会执行失败,并且调用方不需要持有 attached thread state

参见

threading.get_ident() and threading.Thread.ident expose this identifier to Python.

PyObject *PyThread_GetInfo(void)
属于 稳定 ABI 自 3.3 版起.

获取有关当前线程的 结构体序列 对象形式的基本信息。此信息可在 Python 中作为 sys.thread_info 访问。

成功时,此函数将返回一个指向线程信息的新的 strong reference;失败时,将返回 NULL 并设置一个异常。

调用方必须持有一个 attached thread state

PY_HAVE_THREAD_NATIVE_ID

该宏将在系统支持原生线程 ID 时被定义。

unsigned long PyThread_get_thread_native_id(void)
属于 稳定 ABI on platforms with native thread IDs.

获取当前线程由操作系统的内核所分配的原生标识号,它绝对不会小于零。

此函数仅在定义了 PY_HAVE_THREAD_NATIVE_ID 时可用。

此函数不会执行失败,并且调用方不需要持有 attached thread state

void PyThread_exit_thread(void)
属于 稳定 ABI.

终结当前线程。此函数通常被视为是不安全的并应避免使用。它只是为了向下兼容而被保留。

此函数仅在整个调用栈中的所有函数都被编写为能够安全地支持它时才能被安全地调用。

警告

如果当前系统使用 POSIX 线程(或称“p 线程”),此函数将调用 pthread_exit(3),它会尝试展开栈并在某些 libc 实现上调用 C++ 析构器,如果抵达一个 noexcept 函数,它可能会终结进程。在其他系统,如 macOS 上,只执行展开。

在 Windows 上,此函数将调用 _endthreadex(),它将杀掉线程而不调用 C++ 析构器。

在任何情况下,都存在线程栈损坏的风险。

自 3.14 版本弃用.

void PyThread_init_thread(void)
属于 稳定 ABI.

初始化 PyThread* API。Python 会自动执行此函数,因此很少需要从扩展模块调用它。

int PyThread_set_stacksize(size_t size)
属于 稳定 ABI.

将当前线程的栈大小设为 size 个字节。

此函数成功时返回 0,如果 size 无效则返回 -1,或者如果系统不支持修改栈大小则返回 -2。此函数不会设置异常。

调用方不需要持有 attached thread state

size_t PyThread_get_stacksize(void)
属于 稳定 ABI.

返回以字节为单位的当前线程栈大小,或者如果是使用系统的默认栈大小则返回 0

调用方不需要持有 attached thread state