_thread
— 低级线程 API¶
此模块提供了用于处理多线程(也称为轻量级进程或任务)的低级原语,即多个控制线程共享其全局数据空间。 为了进行同步,提供了简单的锁(也称为互斥锁或二进制信号量)。 threading
模块在此模块的基础上提供了一个更易于使用和更高级的线程 API。
版本 3.7 中的变化: 此模块以前是可选的,现在始终可用。
此模块定义了以下常量和函数
- 异常 _thread.error¶
在线程特定错误时引发。
版本 3.3 中的变化: 现在这是内置
RuntimeError
的同义词。
- _thread.LockType¶
这是锁对象的类型。
- _thread.start_new_thread(function, args[, kwargs])¶
启动一个新线程并返回其标识符。 该线程使用参数列表 *args*(必须是元组)执行函数 *function*。 可选的 *kwargs* 参数指定关键字参数的字典。
当函数返回时,线程将静默退出。
当函数因未处理的异常而终止时,将调用
sys.unraisablehook()
来处理该异常。 hook 参数的 *object* 属性是 *function*。 默认情况下,将打印堆栈跟踪,然后线程退出(但其他线程继续运行)。当函数引发
SystemExit
异常时,将静默忽略它。引发带有参数
function
、args
、kwargs
的 审计事件_thread.start_new_thread
。版本 3.8 中的变化: 现在使用
sys.unraisablehook()
来处理未处理的异常。
- _thread.interrupt_main(signum=signal.SIGINT, /)¶
模拟主线程中到达信号的效果。 线程可以使用此函数来中断主线程,尽管不能保证中断会立即发生。
如果给出,*signum* 是要模拟的信号编号。 如果未给出 *signum*,则模拟
signal.SIGINT
。如果 Python 未处理给定的信号(它被设置为
signal.SIG_DFL
或signal.SIG_IGN
),则此函数不执行任何操作。版本 3.10 中的变化: 添加了 *signum* 参数以自定义信号编号。
注意
这不会发出相应的信号,而是安排对关联处理程序的调用(如果存在)。 如果你想真正发出信号,请使用
signal.raise_signal()
。
- _thread.exit()¶
引发
SystemExit
异常。 如果未捕获,这将导致线程静默退出。
- _thread.allocate_lock()¶
返回一个新的锁对象。 锁的方法如下所述。 锁最初处于解锁状态。
- _thread.get_ident()¶
返回当前线程的“线程标识符”。 这是一个非零整数。 它的值没有直接含义; 它旨在作为魔术cookie,例如用于索引线程特定数据的字典。 当一个线程退出并创建另一个线程时,线程标识符可能会被回收。
- _thread.get_native_id()¶
返回由内核分配的当前线程的本机整数线程 ID。 这是一个非负整数。 它的值可用于在系统范围内唯一标识此特定线程(直到线程终止,之后该值可能会被操作系统回收)。
可用性:Windows、FreeBSD、Linux、macOS、OpenBSD、NetBSD、AIX、DragonFlyBSD。
3.8 版新增。
- _thread.stack_size([size])¶
返回创建新线程时使用的线程堆栈大小。可选的 *size* 参数指定随后创建的线程要使用的堆栈大小,并且必须为 0(使用平台或配置的默认值)或至少为 32,768(32 KiB)的正整数值。如果未指定 *size*,则使用 0。如果不支持更改线程堆栈大小,则会引发
RuntimeError
。如果指定的堆栈大小无效,则会引发ValueError
,并且堆栈大小不会被修改。32 KiB 是当前支持的最小堆栈大小值,以保证解释器本身有足够的堆栈空间。请注意,某些平台可能对堆栈大小的值有特殊的限制,例如要求最小堆栈大小 > 32 KiB 或要求以系统内存页面大小的倍数进行分配 - 应参考平台文档以获取更多信息(4 KiB 页面很常见;在没有更具体信息的情况下,建议使用 4096 的倍数作为堆栈大小)。可用性:Windows、pthreads。
支持 POSIX 线程的 Unix 平台。
- _thread.TIMEOUT_MAX¶
Lock.acquire
的 *timeout* 参数允许的最大值。指定大于此值的超时将引发OverflowError
。3.2 版新增。
Lock 对象具有以下方法
- lock.acquire(blocking=True, timeout=-1)¶
没有任何可选参数时,此方法将无条件地获取锁,如有必要,将一直等待,直到它被另一个线程释放(一次只有一个线程可以获取锁 - 这就是它们存在的原因)。
如果存在 *blocking* 参数,则操作取决于其值:如果为 false,则仅当可以立即获取锁而无需等待时才获取锁,而如果为 true,则如上所述无条件地获取锁。
如果存在浮点型 *timeout* 参数且为正数,则它指定返回之前的最长等待时间(以秒为单位)。负的 *timeout* 参数指定无限期等待。如果 *blocking* 为 false,则不能指定 *timeout*。
如果成功获取锁,则返回值为
True
,否则为False
。3.2 版更改: *timeout* 参数是新增的。
3.2 版更改: 现在可以通过 POSIX 上的信号中断锁获取。
- lock.release()¶
释放锁。锁必须先前已获取,但不一定是同一线程获取的。
- lock.locked()¶
返回锁的状态:如果已被某个线程获取,则为
True
,否则为False
。
除了这些方法之外,还可以通过 with
语句使用锁对象,例如
import _thread
a_lock = _thread.allocate_lock()
with a_lock:
print("a_lock is locked while this executes")
注意事项
线程与中断的交互方式很奇怪:
KeyboardInterrupt
异常将由任意线程接收。(当signal
模块可用时,中断始终会转到主线程。)调用
sys.exit()
或引发SystemExit
异常等效于调用_thread.exit()
。无法中断锁上的
acquire()
方法 -KeyboardInterrupt
异常将在获取锁后发生。当主线程退出时,其他线程是否存活取决于系统定义。在大多数系统上,它们会在不执行
try
…finally
子句或执行对象析构函数的情况下被终止。