_thread —低级线程 API


该模块提供了用于处理多个线程(也称为“轻量级进程”或“任务”)的低级 Primitives-多个控制线程共享其全局数据空间。为了进行同步,提供了简单的锁(也称为* mutexes binary semaphores *)。 threading模块提供了更易于使用的Function,并在此模块的顶部构建了更高级别的线程 API。

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

该模块定义以下常量和函数:

  • exception _thread. error
    • 引发特定于线程的错误。

在版本 3.3 中进行了更改:现在,它是内置RuntimeError的同义词。

  • _thread. LockType

    • 这是锁定对象的类型。
  • _thread. start_new_thread(* function args * [,* kwargs *])

    • 启动一个新线程并返回其标识符。线程执行带有参数列表* args (必须为 Tuples)的Function function 。可选的 kwargs *参数指定关键字参数的字典。

当函数返回时,线程以静默方式退出。

当函数以未处理的异常终止时,将调用sys.unraisablehook()来处理该异常。 hook 参数的* object 属性是 function *。默认情况下,将打印堆栈跟踪,然后线程退出(但其他线程 continue 运行)。

当函数引发SystemExit异常时,它将被静默忽略。

在 3.8 版中进行了更改:sys.unraisablehook()现在用于处理未处理的异常。

  • _thread. interrupt_main ( )
    • 模拟signal.SIGINTsignal 到达主线程的效果。线程可以使用此Function来break主线程。

如果signal.SIGINT不是由 Python 处理(将其设置为signal.SIG_DFLsignal.SIG_IGN),则此函数不执行任何操作。

  • _thread. exit ( )

    • 引发SystemExitexception。如果未被捕获,这将导致线程静默退出。
  • _thread. allocate_lock ( )

    • 返回一个新的锁对象。锁定方法如下所述。锁最初是解锁的。
  • _thread. get_ident ( )

    • 返回当前线程的“线程标识符”。这是一个非零整数。它的值没有直接的意义。它旨在用作魔术 Cookies,例如为线程专用数据字典构建索引。当一个线程退出并创建另一个线程时,线程标识符可以被回收。
  • _thread. get_native_id ( )

    • 返回内核分配的当前线程的本机整数 Thread ID。这是一个非负整数。它的值可用于在系统范围内唯一标识此特定线程(直到线程终止,然后该值可由 OS 回收)。

Availability:Windows,FreeBSD,Linux,macOS,OpenBSD,NetBSD,AIX。

3.8 版的新Function。

  • _thread. stack_size([* size *])
    • 返回创建新线程时使用的线程堆栈大小。可选的* size 参数指定要用于后续创建的线程的堆栈大小,并且必须为 0(使用平台或配置的默认值)或至少 32,768(32 KiB)的正整数。如果未指定 size *,则使用 0.如果不支持更改线程堆栈大小,则会引发RuntimeError。如果指定的堆栈大小无效,则会引发ValueError且堆栈大小不会被修改。当前,支持的最小堆栈大小值为 32 KiB,以保证解释程序本身有足够的堆栈空间。请注意,某些平台可能会对堆栈大小的值有特定限制,例如要求最小堆栈大小> 32 KiB 或要求以系统内存页面大小的倍数进行分配-有关更多信息,请参阅平台文档(4 KiB 页面)很常见;在缺少更多具体信息的情况下,建议使用 4096 的倍数作为堆栈大小)。

Availability:Windows,具有 POSIX 线程的系统。

  • _thread. TIMEOUT_MAX
    • Lock.acquire()的* timeout *参数所允许的最大值。指定的超时值大于此值将引发OverflowError

3.2 版中的新Function。

锁定对象具有以下方法:

  • lock. acquire(* waitflag = 1 timeout = -1 *)
    • 如果没有任何可选参数,则此方法无条件获取该锁,必要时可以 await 它被另一个线程释放(一次只能有一个线程可以获取锁-这就是它们存在的原因)。

如果存在整数* waitflag *,则操作取决于其值:如果为零,则仅当无需 await 就可以立即获取锁时才获取锁,而如果为非零,则如上所述那样无条件获取锁。

如果浮点* timeout 参数存在且为正数,则它指定返回前的最大 await 时间(以秒为单位)。负的 timeout 参数指定无限制的 await。如果 waitflag 为零,则不能指定 timeout *。

如果成功获取了锁,则返回值为True,否则为False

在版本 3.2 中更改:* timeout *参数是新的。

在版本 3.2 中更改:锁获取现在可以被 POSIX 上的 signal break。

  • lock. release ( )

    • 释放锁。该锁必须是较早获得的,但不一定是由同一线程获得的。
  • lock. locked ( )

    • 返回锁的状态:True(如果已被某个线程获取),False(如果不是)。

除了这些方法外,还可以passwith语句使用锁定对象,例如:

import _thread

a_lock = _thread.allocate_lock()

with a_lock:
    print("a_lock is locked while this executes")

Caveats:

Note

  • 线程与break发生奇怪的交互:KeyboardInterrupt异常将被任意线程接收。 (当signal模块可用时,break总是转到主线程。)

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

  • 无法break锁上的acquire()方法-KeyboardInterrupt异常将在获取锁后发生。

  • 当主线程退出时,系统定义其他线程是否存活。在大多数系统上,它们是在不执行tryfinally子句或执行对象析构函数的情况下被杀死的。

  • 当主线程退出时,它不执行任何常规清理操作(除了使用tryfinally子句外),并且不刷新标准 I/O 文件。