_thread — 底层线程 API


此模块为使用多线程(也称为轻量级进程任务)提供了底层原语 - 共享其全局数据空间的多个控制线程。 为了同步,提供了简单的锁(也称为互斥锁二进制信号量)。 threading 模块在此模块之上构建,提供了更易于使用和更高级的线程 API。

在 3.7 版本中变更: 此模块以前是可选的,现在始终可用。

此模块定义了以下常量和函数

exception _thread.error

在特定于线程的错误时引发。

在 3.3 版本中变更: 现在它是内置的 RuntimeError 的同义词。

_thread.LockType

这是锁对象的类型。

_thread.start_new_thread(function, args[, kwargs])

启动一个新线程并返回其标识符。该线程使用参数列表 args (必须是元组)执行函数 function。 可选的 kwargs 参数指定关键字参数的字典。

当函数返回时,该线程会静默退出。

当函数因未处理的异常而终止时,将调用 sys.unraisablehook() 来处理该异常。 钩子参数的 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_DFLsignal.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、GNU/kFreeBSD。

在 3.8 版本中添加。

在 3.13 版本中变更: 添加了对 GNU/kFreeBSD 的支持。

_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.acquiretimeout 参数允许的最大值。 指定大于此值的超时将引发 OverflowError

在 3.2 版本中添加。

锁对象具有以下方法

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 异常将由该线程接收。)

  • 调用 sys.exit() 或引发 SystemExit 异常等同于调用 _thread.exit()

  • 锁上的 acquire() 方法是否可以被中断(以便 KeyboardInterrupt 异常立即发生,而不是在锁被获取或操作超时后才发生),这取决于平台。在 POSIX 上可以被中断,但在 Windows 上则不行。

  • 当主线程退出时,其他线程是否继续存活取决于系统定义。在大多数系统上,它们会被终止,而不会执行 try ... finally 子句或执行对象析构函数。