python / 3.7.2rc1 / all / library-threading.html

线程化—基于线程的并行性

源代码: Lib/threading.py


该模块在较低级别的_thread模块之上构造较高级别的线程接口。另请参见queue模块。

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

Note

尽管下面未列出,但该模块仍支持 python_ 2.x 系列中此模块的某些方法和Function所使用的camelCase名称。

该模块定义以下Function:

  • threading. active_count ( )

    • 返回当前处于活动状态的Thread个对象的数量。返回的计数等于enumerate()返回的列表的长度。
  • threading. current_thread ( )

    • 返回与调用者的控制线程相对应的当前Thread对象。如果调用者的控制线程不是passthreading模块创建的,则返回Function有限的虚拟线程对象。
  • threading. excepthook(* args /*)

  • args *参数具有以下属性:
    • exc_type *:异常类型。
    • exc_value *:异常值,可以为None
    • exc_traceback *:异常跟踪,可以为None
    • thread *:引发异常的线程可以是None

如果* exc_type *为SystemExit,则忽略该异常。否则,异常会打印在sys.stderr上。

如果此函数引发异常,则调用sys.excepthook()来处理它。

可以覆盖threading.excepthook()以控制如何处理Thread.run()引发的未捕获异常。

使用自定义钩子存储* exc_value *可以创建参考周期。当不再需要异常时,应明确清除它以 break 参考周期。

如果将* thread 设置为要finally确定的对象,则使用自定义钩子存储 thread 可以使它复活。避免在自定义钩子完成后存储 thread *,以免复活对象。

See also

sys.excepthook()处理未捕获的异常。

3.8 版的新Function。

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

版本 3.3 中的新Function。

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

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

3.8 版的新Function。

  • threading. enumerate ( )

    • 返回当前所有活动的Thread个对象的列表。该列表包括守护线程,由current_thread()创建的伪线程对象和主线程。它不包括终止的线程和尚未启动的线程。
  • threading. main_thread ( )

    • 返回主要的Thread对象。在正常情况下,主线程是启动 Python 解释器的线程。

3.4 版的新Function。

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

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

此模块还定义以下常量:

3.2 版中的新Function。

该模块定义了许多类,在以下各节中将进行详细介绍。

该模块的设计大致基于 Java 的线程模型。但是,在 Java 使锁和条件变量成为每个对象的基本行为的地方,它们是 Python 中单独的对象。 Python 的Thread类支持 Java 的 Thread 类的行为的子集;当前,没有优先级,没有线程组,并且无法破坏,停止,挂起,恢复或break线程。 Java 的 Thread 类的静态方法在实现后会 Map 到模块级函数。

下述所有方法都是原子执行的。

Thread-Local Data

线程本地数据是其值是特定于线程的数据。要 Management 线程本地数据,只需创建local(或子类)的实例并在其上存储属性:

mydata = threading.local()
mydata.x = 1

对于单独的线程,实例的值将有所不同。

  • 类别 threading. local
    • 表示线程本地数据的类。

有关更多详细信息和大量示例,请参见_threading_local模块的文档字符串。

Thread Objects

Thread类表示在单独的控制线程中运行的活动。有两种指定活动的方法:pass将可调用对象传递给构造函数,或pass重写子类中的run()方法。子类中不应覆盖其他任何方法(构造函数除外)。换句话说,* only *覆盖了此类的__init__()run()方法。

创建线程对象后,必须pass调用线程的start()方法来启动其活动。这将在单独的控制线程中调用run()方法。

一旦线程的活动开始,该线程即被视为“活动”。当它的run()方法终止时,它会停止运行-无论是正常运行还是引发未处理的异常。 is_alive()方法测试线程是否处于活动状态。

其他线程可以调用线程的join()方法。这将阻塞调用线程,直到终止调用join()方法的线程为止。

线程具有名称。该名称可以传递给构造函数,并可以passname属性读取或更改。

如果run()方法引发异常,则调用threading.excepthook()处理该异常。默认情况下,threading.excepthook()默默地忽略SystemExit

线程可以标记为“守护程序线程”。该标志的重要性在于,仅保留守护程序线程时,整个 Python 程序都会退出。初始值是从创建线程继承的。可以passdaemon属性或* daemon *构造函数参数设置该标志。

Note

守护程序线程在关闭时突然停止。它们的资源(例如打开的文件,数据库事务等)可能无法正确释放。如果希望线程正常停止,请使其成为非守护线程,并使用合适的 signal 传递机制,例如Event

有一个“主线程”对象;这对应于 Python 程序中的初始控制线程。它不是守护程序线程。

有可能创建了“虚拟线程对象”。这些是与“外来线程”相对应的线程对象,“外来线程”是在线程模块外部启动的控制线程,例如直接从 C 代码开始的线程。虚拟线程对象的Function有限。它们始终被认为是活动的和守护程序,不能被join() ed。它们永远不会被删除,因为不可能检测到外来线程的终止。

    • class * threading. Thread(* group = None target = None name = None args =() kwargs ={} **,* daemon = None *)
    • 始终应使用关键字参数来调用此构造函数。参数为:
  • group *应该为None;当实现ThreadGroup类时保留给以后的扩展。

  • target *是由run()方法调用的可调用对象。默认值为None,表示什么都不会被调用。

  • name *是线程名称。默认情况下,唯一名称的格式为“ Thread- * N ”,其中 N *是一个小十进制数字。

  • args *是目标调用的参数 Tuples。默认为()

  • kwargs *是用于目标调用的关键字参数字典。默认为{}

如果不是None,则* daemon *显式设置线程是否为守护程序。如果None(默认值),则守护程序属性将从当前线程继承。

如果子类覆盖了构造函数,则必须确保在对线程执行其他任何操作之前调用 Base Class 的构造函数(Thread.__init__())。

在版本 3.3 中更改:添加了* daemon *参数。

  • start ( )
    • 启动线程的活动。

每个线程对象最多只能调用一次。它安排在单独的控制线程中调用对象的run()方法。

如果在同一线程对象上多次调用此方法,则将引发RuntimeError

  • run ( )
    • 表示线程活动的方法。

您可以在子类中重写此方法。标准的run()方法调用传递给对象构造函数的可调用对象作为* target 参数(如果有),并分别从 args kwargs *参数中获取位置和关键字参数。

  • join(* timeout = None *)
    • await 线程终止。这将阻塞调用线程,直到被调用join()方法的线程终止(正常或pass未处理的异常终止),或者直到发生可选的超时。

当存在* timeout *参数而不是None时,它应该是一个浮点数,以秒为单位(或其分数)指定操作的超时时间。由于join()始终返回None,因此您必须在join()之后调用is_alive()来确定是否发生超时–如果线程仍然存在,则join()调用超时。

当* timeout *参数不存在或None时,该操作将阻塞直到线程终止。

一个线程可以被多次join()编辑。

如果try加入当前线程,则join()引发RuntimeError,因为这将导致死锁。在启动线程之前join()一个线程也是一个错误,try这样做会引发相同的异常。

  • name

    • 仅用于标识目的的字符串。它没有语义。多个线程可以被赋予相同的名称。初始名称由构造函数设置。
  • getName ( )

    • setName ( )
      • name的旧的 getter/setter API;直接将其用作属性。
  • ident

    • 此线程的“线程标识符”;如果尚未启动该线程,则返回None。这是一个非零整数。请参阅get_ident()Function。当一个线程退出并创建另一个线程时,线程标识符可以被回收。该标识符即使在线程退出后仍然可用。
  • native_id

    • 该线程的本机整数线程 ID。这是一个非负整数,如果尚未启动线程,则为None。请参阅get_native_id()Function。这表示由 os(内核)分配给线程的线程 ID(TID)。它的值可用于在系统范围内唯一标识此特定线程(直到线程终止,然后该值可由 OS 回收)。

Note

与进程 ID 相似,线程 ID 仅在创建线程到终止线程之间才有效(确保系统范围内唯一)。

Availability:需要get_native_id()Function。

3.8 版的新Function。

  • is_alive ( )
    • 返回线程是否处于活动状态。

此方法将在run()方法开始之前返回True,直到run()方法终止之后。模块函数enumerate()返回所有活动线程的列表。

  • daemon
    • 一个布尔值,指示此线程是否是守护线程(真)(假)。必须在调用start()之前设置此项,否则引发RuntimeError。它的初始值是从创建线程继承的;主线程不是守护程序线程,因此在主线程中创建的所有线程默认为daemon = False

当没有活动的非守护线程时,整个 Python 程序将退出。

  • isDaemon ( )
    • setDaemon ( )
      • daemon的旧的 getter/setter API;直接将其用作属性。

CPython 实现细节: 在 CPython 中,由于全局翻译锁,只有一个线程可以一次执行 Python 代码(即使某些面向性能的库可能克服了此限制)。如果希望您的应用程序更好地利用多核计算机的计算资源,建议使用multiprocessingconcurrent.futures.ProcessPoolExecutor。但是,如果您要同时运行多个 I/O 绑定任务,则线程化仍然是合适的模型。

Lock Objects

Primitives 锁是一种同步 Primitives,锁定后该 Primitives 不属于特定线程。在 Python 中,它是当前可用的最低级别的同步 Primitives,由_thread扩展模块直接实现。

基本锁处于“已锁定”或“未锁定”两种状态之一。它是在解锁状态下创建的。它有两种基本方法,acquire()release()。解锁状态后,acquire()会将状态更改为锁定并立即返回。当状态锁定时,acquire()阻塞,直到在另一个线程中对release()的调用将其更改为未锁定,然后acquire()调用将其重置为锁定并返回。只能在锁定状态下调用release()方法。它将状态更改为解锁并立即返回。如果try释放解锁的锁,则会引发RuntimeError

锁也支持上下文 Management 协议

acquire()中有多个线程被阻塞以 await 状态变为解锁时,当release()调用将状态重置为解锁时,只有一个线程 continue 前进;await 线程之一 continue 前进的过程尚未定义,并且可能因实现而异。

所有方法都是原子执行的。

  • 类别 threading. Lock
    • 实现原始锁对象的类。一旦线程获取了锁,随后的try将其阻塞,直到释放为止。任何线程都可以释放它。

请注意,Lock实际上是一个工厂函数,它返回平台支持的具体 Lock 类的最高效版本的实例。

  • acquire(* blocking = True timeout = -1 *)
    • 获取锁定,阻止或非阻止。

在将* blocking *参数设置为True(默认值)的情况下调用时,阻塞直到锁被解锁,然后将其设置为 locked 并返回True

在将* blocking 参数设置为False的情况下调用时,请勿进行阻止。如果将 blocking *设置为True的呼叫阻塞,请立即返回False;否则,将锁设置为锁定并返回True

在将浮点* timeout 参数设置为正值的情况下调用时,最多阻塞一次由 timeout *指定的秒数,并且只要无法获取该锁即可。 * timeout 参数-1指定无限制的 await。如果 blocking 为 false,则禁止指定 timeout *。

如果成功获取了锁,则返回值为True,否则返回False(例如* timeout *过期)。

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

在版本 3.2 中更改:现在,如果基础线程实现支持,则可以pass POSIX 上的 signal 来break锁获取。

  • release ( )
    • 释放锁。可以从任何线程调用此函数,而不仅仅是获得锁的线程。

锁锁定后,将其重置为解锁状态,然后返回。如果其他任何线程被阻塞,await 锁解锁,则只允许其中一个 continue 进行。

在解锁的锁上调用时,将引发RuntimeError

没有返回值。

  • locked ( )
    • 如果获得了锁,则返回 true。

RLock Objects

可重入锁是一个同步 Primitives,可以由同一线程多次获取。在内部,除了原始锁使用的锁定/解锁状态外,它还使用“拥有线程”和“递归级别”的概念。在锁定状态下,某些线程拥有该锁;在解锁状态下,没有线程拥有它。

要锁定该锁,线程调用其acquire()方法。一旦线程拥有锁,它将返回。要解锁该锁,线程将调用其release()方法。 acquire()/release()呼叫对可以嵌套;只有最后的release()(最外面的对中的release())会将锁重置为解锁状态,并允许在acquire()中阻塞的另一个线程 continue 进行。

可重入锁也支持上下文 Management 协议

  • 类别 threading. RLock
    • 此类实现可重入锁定对象。可重入锁必须由获取它的线程释放。一旦线程获取了可重入锁,同一线程就可以再次获取它而不会阻塞;线程必须在每次获取它后释放一次。

请注意,RLock实际上是一个工厂函数,它返回平台支持的具体 RLock 类的最高效版本的实例。

  • acquire(* blocking = True timeout = -1 *)
    • 获取锁定,阻止或非阻止。

在不带参数的情况下调用时:如果此线程已拥有锁,则将递归级别增加 1,然后立即返回。否则,如果另一个线程拥有该锁,则阻塞直到锁被解锁。一旦锁被解锁(不属于任何线程),然后获取所有权,将递归级别设置为 1,然后返回。如果阻塞了多个线程,直到锁被解锁,则一次只能获取一个线程的所有权。在这种情况下,没有返回值。

在将* blocking *参数设置为 true 的情况下调用时,请执行与不带参数的调用相同的操作,并返回True

在将* blocking *参数设置为 false 的情况下调用时,请勿阻塞。如果没有参数的呼叫阻塞,请立即返回False;否则,执行与不带参数调用时相同的操作,并返回True

在将浮点* timeout 参数设置为正值的情况下调用时,最多阻塞一次由 timeout *指定的秒数,并且只要无法获取该锁即可。如果已获取锁定,则返回True;如果超时则返回 false。

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

  • release ( )
    • 释放一个锁,递归级别递减。如果递减后为零,则将锁重置为解锁状态(不属于任何线程),并且如果其他任何线程被阻塞,await 锁被解锁,则允许其中一个 continue 进行。如果在递减之后递归级别仍然不为零,则锁保持锁定并由调用线程拥有。

仅在调用线程拥有锁时才调用此方法。如果在解锁时调用此方法,则会引发RuntimeError

没有返回值。

Condition Objects

条件变量总是与某种锁定相关联。可以传入,也可以默认创建一个。当多个条件变量必须共享相同的锁时,传递一个 Importing 很有用。锁是条件对象的一部分:您不必单独跟踪它。

条件变量遵循上下文 Management 协议:使用with语句在封闭块的持续时间内获取关联的锁。 acquire()release()方法还调用关联锁的相应方法。

必须使用关联的锁来调用其他方法。 wait()方法释放该锁,然后阻塞,直到另一个线程pass调用notify()notify_all()将其唤醒。唤醒后,wait()重新获取锁并返回。也可以指定超时。

notify()方法唤醒一个 await 条件变量的线程(如果有)在 await。 notify_all()方法唤醒所有 await 条件变量的线程。

注意:notify()notify_all()方法不会释放该锁;这意味着被唤醒的一个或多个线程不会立即从其wait()调用返回,而是仅在调用notify()notify_all()的线程finally放弃该锁的所有权时才返回。

典型的使用条件变量的编程风格使用锁来同步对某些共享状态的访问。对状态的特定更改感兴趣的线程会反复调用wait(),直到看到所需的状态为止;而对状态进行修改的线程会在它们以某种可能成为所需状态的方式更改状态时调用notify()notify_all()。那些服务员。例如,以下代码是具有无限缓冲区容量的一般生产者-Consumer 情况:

# Consume one item
with cv:
    while not an_item_is_available():
        cv.wait()
    get_an_available_item()

# Produce one item
with cv:
    make_an_item_available()
    cv.notify()

while循环检查应用程序的条件是必要的,因为wait()可以在任意长时间后返回,并且提示notify()调用的条件可能不再成立。这是多线程编程所固有的。 wait_for()方法可用于自动进行条件检查,并简化超时的计算:

# Consume an item
with cv:
    cv.wait_for(an_item_is_available)
    get_an_available_item()

要在notify()notify_all()之间进行选择,请考虑只对一个或几个 await 线程进行一次状态更改是否有意义。例如。在典型的生产者-Consumer 情况下,向缓冲区添加一项仅需要唤醒一个 Consumer 线程。

    • class * threading. Condition(* lock = None *)
    • 此类实现条件变量对象。条件变量允许一个或多个线程 await,直到被另一个线程通知为止。

如果给定* lock *参数而不是None,则它必须是LockRLock对象,并且用作基础锁。否则,将创建一个新的RLock对象,并将其用作基础锁。

在版本 3.3 中更改:从工厂Function更改为类。

  • acquire(** args *)

    • 获取基础锁。该方法在基础锁上调用相应的方法;返回值就是该方法返回的值。
  • release ( )

    • 释放基础锁。该方法在基础锁上调用相应的方法;没有返回值。
  • wait(* timeout = None *)

    • await 直到收到通知或超时。如果在调用此方法时调用线程未获取锁,则会引发RuntimeError

此方法释放基础锁,然后进行阻塞,直到被另一个线程中的相同条件变量的notify()notify_all()调用唤醒它为止,或者直到发生可选的超时为止。一旦唤醒或超时,它将重新获取锁并返回。

当存在* timeout *参数而不是None时,它应该是一个浮点数,用于指定操作的超时时间(以秒为单位)。

当基础锁是RLock时,不会使用其release()方法释放它,因为当递归多次获取锁时,它实际上可能无法解锁。而是使用RLock类的内部接口,即使递归获取了几次,它也可以 true 将其解锁。重新获得锁定后,另一个内部接口将用于恢复递归级别。

除非给定的* timeout *过期,否则返回值为True,在这种情况下为False

在版本 3.2 中更改:以前,该方法始终返回None

  • wait_for(* predicate timeout = None *)
    • 等到条件评估为真。 * predicate 应该是可调用的,其结果将被解释为布尔值。可以提供 timeout *(超时),以提供最大的 await 时间。

该 Util 方法可以重复调用wait(),直到满足该谓词或直到发生超时为止。返回值是谓词的最后一个返回值,如果该方法超时,则返回值为False

忽略超时Function,调用此方法大致等同于编写:

while not predicate():
    cv.wait()

因此,适用与wait()相同的规则:调用时必须保留该锁,并在返回时重新获取该锁。谓词在持有锁的情况下进行评估。

3.2 版中的新Function。

  • notify(* n = 1 *)
    • 默认情况下,唤醒一个线程 await 这种情况(如果有)。如果在调用此方法时调用线程未获取锁,则会引发RuntimeError

该方法最多唤醒* n *个 await 条件变量的线程;如果没有线程正在 await,则为空操作。

如果至少有* n 个线程正在 await,则当前实现会精确地唤醒 n 个线程。但是,依靠这种行为并不安全。Future 的优化实现有时可能会唤醒 n *个线程。

注意:唤醒的线程直到可以重新获取锁定后才 true 从其wait()调用返回。由于notify()不会释放锁,因此它的调用方应该。

  • notify_all ( )
    • 唤醒所有在这种情况下 await 的线程。此方法的作用类似于notify(),但是唤醒所有 await 的线程,而不是一个。如果在调用此方法时调用线程未获取锁,则会引发RuntimeError

Semaphore Objects

这是计算机科学史上最古老的同步 Primitives 之一,由荷兰早期计算机科学家 Edsger W. Dijkstra 发明(他使用名称P()V()代替acquire()release())。

signal 量 Management 一个内部计数器,该内部计数器由每个acquire()调用递减,并由每个release()调用递增。计数器永远不能低于零。当acquire()发现它为零时,它将阻塞,直到其他线程调用release()为止。

signal 量也支持上下文 Management 协议

  • 类别 threading. Semaphore(*值= 1 *)
    • 此类实现 signal 量对象。signal 量 Management 一个原子计数器,该计数器代表release()个调用的数量减去acquire()个调用的数量以及初始值。 acquire()方法在必要时会阻塞,直到可以返回而不会使计数器为负数为止。如果未给出,则* value *默认为 1.

可选参数提供内部计数器的初始* value ;默认为1。如果给定的值*小于 0,则引发ValueError

在版本 3.3 中更改:从工厂Function更改为类。

  • acquire(* blocking = True timeout = None *)
    • 获取 signal 量。

不带参数调用时:

  • 如果内部计数器在 Importing 时大于零,则将其递减 1 并立即返回True

  • 如果内部计数器在进入时为零,请阻塞直到被调用release()唤醒为止。一旦唤醒(并且计数器大于 0),将计数器减 1 并返回True。每次调用release()都会唤醒一个线程。不应依赖线程唤醒的 Sequences。

在将* blocking *设置为 false 的情况下调用时,请勿进行阻止。如果没有参数的呼叫阻塞,请立即返回False;否则,执行与不带参数调用时相同的操作,并返回True

当使用非None的* timeout 调用时,它将最多阻塞 timeout *秒。如果获取未在该时间间隔内成功完成,则返回False。否则返回True

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

  • release ( )

    • 释放 signal 量,使内部计数器增加一。当它在进入时为零并且另一个线程正在 await 它再次变得大于零时,唤醒该线程。
  • 类别 threading. BoundedSemaphore(*值= 1 *)

    • 实现有界 signal 量对象的类。有界 signal 量会检查以确保其当前值不超过其初始值。如果是,则引发ValueError。在大多数情况下,signal 量用于保护容量有限的资源。如果 signal 量被释放太多次,则表明存在错误。如果未给出,则* value *默认为 1.

在版本 3.3 中更改:从工厂Function更改为类。

Semaphore Example

signal 量通常用于保护容量有限的资源,例如数据库服务器。在资源大小固定的任何情况下,都应使用有界 signal 量。在产生任何工作线程之前,您的主线程将初始化 signal 量:

maxconnections = 5
# ...
pool_sema = BoundedSemaphore(value=maxconnections)

产生后,辅助线程在需要连接到服务器时会调用 signal 量的获取和释放方法:

with pool_sema:
    conn = connectdb()
    try:
        # ... use connection ...
    finally:
        conn.close()

有界 signal 量的使用减少了导致 signal 量被释放超过获取量的编程错误不会被检测到的机会。

Event Objects

这是线程之间通信的最简单机制之一:一个线程发出事件 signal,其他线程 await 事件。

事件对象 Management 一个内部标志,该标志可以passset()方法设置为 true,而可以passclear()方法重置为 false。 wait()方法将阻塞,直到该标志为 true。

  • 类别 threading. Event
    • 实现事件对象的类。事件 Management 一个标志,该标志可以passset()方法设置为 true,而可以passclear()方法重置为 false。 wait()方法将阻塞,直到该标志为 true。该标志最初为假。

在版本 3.3 中更改:从工厂Function更改为类。

  • is_set ( )

    • 当且仅当内部标志为 true 时,才返回True
  • set ( )

    • 将内部标志设置为 true。唤醒所有 await 变为真的线程。一旦标记为 true,则调用wait()的线程将完全不会阻塞。
  • clear ( )

    • 将内部标志重置为 false。随后,调用wait()的线程将阻塞,直到调用set()以将内部标志再次设置为 true 为止。
  • wait(* timeout = None *)

    • 阻塞直到内部标志为真。如果内部标志在 Importing 时为 true,请立即返回。否则,阻塞直到另一个线程调用set()将标志设置为 true,或者直到发生可选的超时为止。

当存在 timeout 参数而不是None时,它应该是一个浮点数,以秒(或其分数)指定操作的超时时间。

当且仅当内部标志已设置为 true(在 await 调用之前或 await 开始之后)时,此方法才返回True,因此,除非给出了超时且操作超时,否则它将始终返回True

在版本 3.1 中进行了更改:以前,该方法始终返回None

Timer Objects

此类表示仅在经过一定时间后才应执行的操作-计时器。 TimerThread的子类,因此也可作为创建自定义线程的示例。

与线程一样,计时器pass调用其start()方法来启动。可以pass调用cancel()方法来停止计时器(在其动作开始之前)。计时器在执行其操作之前将 await 的时间间隔可能与用户指定的时间间隔不完全相同。

For example:

def hello():
    print("hello, world")

t = Timer(30.0, hello)
t.start()  # after 30 seconds, "hello, world" will be printed
    • class * threading. Timer(* interval function args = None kwargs = None *)
    • 创建一个计时器,该计时器将在* interval 秒过去之后,使用参数 args 和关键字参数 kwargs 运行 function 。如果 args None(默认值),则将使用一个空列表。如果 kwargs *为None(默认值),则将使用空 dict。

在版本 3.3 中更改:从工厂Function更改为类。

  • cancel ( )
    • 停止计时器,并取消执行计时器的操作。仅当计时器仍处于 await 阶段时,此Function才起作用。

Barrier Objects

3.2 版中的新Function。

此类提供了一个简单的同步 Primitives,供需要互相 await 的固定数量的线程使用。每个线程都试图pass调用wait()方法来越过障碍,并且将阻塞直到所有线程都进行了wait()调用。此时,线程将同时释放。

对于相同数量的线程,可以多次重用此屏障。

例如,这是一种同步 Client 端和服务器线程的简单方法:

b = Barrier(2, timeout=5)

def server():
    start_server()
    b.wait()
    while True:
        connection = accept_connection()
        process_server_connection(connection)

def client():
    b.wait()
    while True:
        connection = make_connection()
        process_client_connection(connection)
    • class * threading. Barrier(* parties action = None timeout = None *)
    • 为* parties 个线程创建一个屏障对象。一个 action (如果提供)是一个可被调用的线程在释放时调用的线程。如果未为wait()方法指定任何值,则 timeout *是默认超时值。
  • wait(* timeout = None *)

    • pass障碍。当屏障的所有线程都调用了此函数后,它们将同时释放。如果提供了* timeout *,则它优先于提供给类构造函数的值使用。

返回值是一个介于 0 到* parties * – 1 之间的整数,每个线程不同。这可以用来选择一个线程来做一些特殊的内务处理,例如:

i = barrier.wait()
if i == 0:
    # Only one thread needs to print this
    print("passed the barrier")

如果将* action *提供给构造函数,则其中一个线程将在释放之前对其进行调用。如果此调用引发错误,则屏障将进入断开状态。

如果呼叫超时,则屏障将进入断开状态。

如果在线程 await 时屏障被破坏或重置,则此方法可能会引发BrokenBarrierError异常。

  • reset ( )
    • 将屏障返回到默认的空状态。await 它的所有线程将收到BrokenBarrierError异常。

请注意,如果还有其他线程的状态未知,则使用此Function可能需要进行一些外部同步。如果障碍被 break,最好留下它并创建一个新的障碍。

  • abort ( )
    • 将屏障置于破碎状态。这会导致对wait()的任何活动或将来的调用都因BrokenBarrierError而失败。例如,如果其中一个线程需要中止,请使用此选项,以避免死锁应用程序。

可能更希望仅使用合理的* timeout *值来创建屏障,以自动防止出现错误的线程之一。

  • parties

    • 穿过屏障所需的线程数。
  • n_waiting

    • 当前在屏障中 await 的线程数。
  • broken

    • 如果障碍处于破碎状态,则为True的布尔值。
  • exception threading. BrokenBarrierError

在 with 语句中使用锁,条件和 signal 量

此模块提供的具有acquire()release()方法的所有对象都可用作with语句的上下文 Management 器。进入该块时将调用acquire()方法,而退出该块时将调用release()。因此,以下代码段:

with some_lock:
    # do something...

等效于:

some_lock.acquire()
try:
    # do something...
finally:
    some_lock.release()

当前,LockRLockConditionSemaphoreBoundedSemaphore对象可用作with语句上下文 Management 器。