线程状态和全局解释器锁¶
除非使用 CPython 的 free-threaded build 版本,否则Python 解释器通常都不是线程安全的。 为了支持多线程的 Python 程序,解释器有一个全局锁,称为 global interpreter lock 或 GIL,线程必须在访问 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 的长时间运行的原生代码。 例如,标准库 zlib 和 hashlib 模块会在对数据执行压缩或哈希运算时分离 线程状态。
在 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.
参见
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
NULLwithout an exception set. Do not callPyThreadState_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_Ensurecall 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 correspondingPyThreadState_Release()call.Added in version 3.15.
-
void PyThreadState_Release(PyThreadStateToken *token)¶
- 属于 稳定 ABI 自 3.15 版起.
Undo a
PyThreadState_Ensure()orPyThreadState_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 correspondingPyThreadState_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 尚未被持有。
-
enumerator PyGILState_LOCKED¶
-
PyGILState_STATE PyGILState_Ensure()¶
- 属于 稳定 ABI.
确保当前线程可以调用 Python C API,无论 Python 的当前状态或 attached thread state 如何。只要每个调用都与对
PyGILState_Release()的调用相匹配,线程就可以根据需要多次调用此函数。通常,只要线程状态在调用 Release() 之前恢复到其先前状态,就可以在PyGILState_Ensure()和PyGILState_Release()调用之间使用其他与线程相关的 API。例如,可以正常使用Py_BEGIN_ALLOW_THREADS和Py_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
SIGABRTand crash the process; seePy_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()orPyThreadState_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 returnsNULL, thenPyGILState_Ensurewill create a new thread state.This function cannot fail.
自 3.15 版起已处于 Soft deprecated 状态: Use
PyThreadState_Get()orPyThreadState_GetUnchecked()instead.
-
int PyGILState_Check()¶
Return
1if the current thread has an attached thread state that matches the thread state returned byPyGILState_GetThisThreadState(). If the caller has no attached thread state or it otherwise doesn't match, then this returns0.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() != NULLinstead.
有关 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¶
该线程的解释器状态。
-
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 *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 state。 tstate 参数必须不为
NULL,该参数仅被用于检查它是否代表 attached thread state --- 如果不是,则会报告一个致命级错误。PyEval_SaveThread()是一个始终可用的(即使线程尚未初始化)更高层级函数。
异步通知¶
提供了一种向主解释器线程发送异步通知的机制。这些通知将采用函数指针和空指针参数的形式。
-
int Py_AddPendingCall(int (*func)(void*), void *arg)¶
- 属于 稳定 ABI.
将一个函数加入从主解释器线程调用的计划任务。成功时,将返回
0并将 func 加入要被主线程调用的等待队列。失败时,将返回-1但不会设置任何异常。当成功加入队列后,func 将 最终 附带参数 arg 被主解释器线程调用。对于正常运行的 Python 代码来说它将被异步地调用,但要同时满足以下两个条件:
位于 bytecode 的边界上;
主线程持有一个 attached thread state (因此 func 可以使用完整的 C API)。
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, orNULLto clear the pending exception (if any).Return the number of affected thread states. This is normally
1if id is found, even when no change was made (the given exc was already pending, or exc isNULLbut no exception is pending). If the thread id isn't found, return0. 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()andthreading.Thread.identexpose 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 版本弃用.
-
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。