threading — 基于线程的并行

源代码: Lib/threading.py


此模块构造更高级线程接口,基于更低级 _thread 模块。另请参阅 queue 模块。

3.7 版改变: 此模块曾经是可选的,现在始终可用。

注意

虽然它们未在以下列出,但 camelCase 名称用于由此模块仍支持的 Python 2.x 系列中的此模块的某些方法和函数。

CPython 实现细节: 在 CPython,由于 全局解释器锁 ,一次仅一线程可以执行 Python 代码 (即使某些面向性能的库可以克服此局限性)。若想让应用程序更好地利用多核机器的计算资源,建议使用 multiprocessing or concurrent.futures.ProcessPoolExecutor 。不管怎样,threading 仍是合适模型若想要同时运行多个 I/O 绑定任务。

此模块定义了下列函数:

threading. active_count ( )

返回数量为 Thread 对象的目前存活。返回计数等于列表长度,列表返回通过 enumerate() .

threading. current_thread ( )

返回当前 Thread 对象,对应调用者控制线程。若调用者控制线程的创建不是透过 threading 模块,返回具有有限功能的虚设线程对象。

threading. excepthook ( args , / )

处理未捕获异常引发通过 Thread.run() .

The args 自变量拥有下列属性:

  • exc_type :异常类型。

  • exc_value :异常值,可以是 None .

  • exc_traceback :异常回溯,可以是 None .

  • thread :引发异常的线程,可以是 None .

exc_type is SystemExit ,异常被默默忽略。否则,异常被打印输出到 sys.stderr .

若此函数引发异常, sys.excepthook() 被调用以处理它。

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

存储 exc_value 使用自定义挂钩可以创建引用循环。应明确清零以中断引用循环,当不再需要异常时。

存储 thread 使用自定义挂钩可以复活它,若它被设为正定稿对象。避免存储 thread 在自定义挂钩完成后以避免复活对象。

另请参阅

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

3.8 版新增。

threading. get_ident ( )

返回当前线程的 "线程标识符"。这是非 0 整数。它的值没有直接意义;旨在作为魔法 Cookie 使用 (如:索引特定线程数据的字典)。线程标识符会被回收,当退出线程并创建另一线程时。

3.3 版新增。

threading. get_native_id ( )

返回由内核赋值的当前线程的本机整形线程 ID。这是非负整数。可以使用它的值唯一标识系统范围内的此特定线程 (直到线程终止,之后 OS 会回收该值)。

可用性 :Windows、FreeBSD、Linux、macOS、OpenBSD、NetBSD、AIX。

3.8 版新增。

threading. enumerate ( )

返回列表为所有 Thread objects currently alive. The list includes daemonic threads, dummy thread objects created by current_thread() , and the main thread. It excludes terminated threads and threads that have not yet been started.

threading. main_thread ( )

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

3.4 版新增。

threading. settrace ( func )

为所有线程设置跟踪函数开始于 threading 模块。 func 将被传递给 sys.settrace() 为各线程,先于其 run() 方法被调用。

threading. setprofile ( func )

为所有线程设置 profile 函数开始于 threading 模块。 func 将被传递给 sys.setprofile() 为各线程,先于其 run() 方法被调用。

threading. stack_size ( [ size ] )

返回创建新线程时使用的线程堆栈大小。可选 size 自变量指定用于随后创建线程的堆栈大小,且必须为 0 (使用平台或配置默认的) 或至少 32,768 (32 KB) 的正整数值。若 size 未指定,使用 0。若不支持改变线程堆栈大小, RuntimeError 被引发。若指定堆栈大小无效, ValueError 被引发且未修改堆栈大小。32 KB 是目前支持的最小堆栈大小值,以保证解释器本身堆栈空间足够。注意,某些平台可能对堆栈大小值有特定限制,譬如要求最小堆栈大小 > 32KB 或要求按系统内存页面大小的倍数分配 - 要了解更多信息请参考平台文档编制 (4KB 页面很常见;建议堆栈大小使用 4096 的倍数方式,当缺乏更具体信息时)。

可用性 :Windows、带有 POSIX 线程的系统。

此模块还定义了下列常量:

threading. TIMEOUT_MAX

最大允许值为 timeout 参数对于阻塞函数 ( Lock.acquire() , RLock.acquire() , Condition.wait() ,等)。指定大于此值的超时将引发 OverflowError .

3.2 版新增。

此模块定义了许多类,以下章节会详细描述。

此模块的设计基于 Java 的松散线程化模型。然而,Java 使锁和条件变量成为每个对象的基本行为,它们在 Python 中是独立对象。Python 的 Thread 类是支持 Java 线程类行为的子集;目前,没有优先级,没有线程组,线程无法被销毁、停止、挂起、恢复或中断。Java 线程类的静态方法,在实现时被映射到了模块级函数。

下文描述的所有方法都以原子方式执行。

线程局部数据

线程局部数据是值为特定线程的数据。要管理线程局部数据,仅仅创建实例化的 local (或子类) 并在其中存储属性:

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

实例的值异于单独线程。

class threading. local

表示线程局部数据的类。

对于更多细节和广泛范例,见文档编制字符串在 _threading_local 模块。

线程对象

The Thread 类表示在单独控制线程中运行的活动。有 2 种方式指定活动:通过将可调用对象传递给构造函数,或通过覆盖 run() 方法在子类中。不应覆盖子类中的其它方法 (除构造函数外)。换句话说, only 覆写 __init__() and run() 方法对于此类。

线程对象一旦被创建,它的活动就必须被启动通过调用线程的 start() 方法。这援引 run() 方法在单独控制线程中。

一旦线程活动开始,就认为线程 "存活"。它将停止存活当其 run() 方法被终止 – 正常或通过引发未处理异常。 is_alive() 方法测试线程是否存活。

其它线程可以调用线程的 join() 方法。这阻塞调用线程,直到线程的 join() 方法被调用才终止。

线程有名称。名称会被传递给构造函数,且读取和改变是透过 name 属性。

run() 方法引发异常, threading.excepthook() 被调用以处理它。默认情况下, threading.excepthook() 默默忽略 SystemExit .

可以将线程标志为 "守护线程"。此标志的意义,整个 Python 程序退出当只剩守护线程时。初始值继承自创建线程。标志可以设置透过 daemon 特性或 daemon 构造函数自变量。

注意

守护线程在关闭时会突然停止。它们的资源 (譬如:打开文件、数据库事务、等) 不可能正确释放。若想要线程优雅停止,使它们成为非守护并使用合适的发信号机制,譬如 Event .

存在 "主线程" 对象;这相当于 Python 程序中的初始控制线程。它不是守护线程。

有可能创建 "虚设线程对象"。这些是 "外来线程" 的对应线程对象,是在 threading 模块外开始的控制线程 (譬如:直接从 C 代码)。虚设线程对象拥有有限功能;认为它们始终存活和守护,且不可以 join() 。它们从不被删除,由于不可能检测外来线程的终止。

class threading. Thread ( group=None , target=None , name=None , args=() , kwargs={} , * , daemon=None )

始终应采用关键词自变量调用此构造函数。自变量:

group 应该为 None ;预留以供未来扩展当 ThreadGroup 类被实现。

target 是要被援引的可调用对象通过 run() 方法。默认为 None ,意味着什么都不调用。

name 是线程名称。默认情况下,唯一名称构造形式为 Thread- N 其中 N 是小十进制数。

args 是援引目标的自变量元组。默认为 () .

kwargs 是援引目标的关键词自变量字典。默认为 {} .

若非 None , daemon 明确设置线程是否为守护线程。若 None (默认),守护特性继承自当前线程。

若子类覆盖构造函数,它必须确保援引基类构造函数 ( Thread.__init__() ) 在对其它线程做任何事情之前。

3.3 版改变: 添加 daemon 自变量。

start ( )

启动线程活动。

每个线程对象必须最多调用它一次。它安排对象的 run() 方法以在单独控制线程中被援引。

此方法将引发 RuntimeError 若在同一线程对象中多次调用。

run ( )

表示线程活动的方法。

可以在子类中覆盖此方法。标准 run() 方法援引传递给对象构造函数的可调用对象作为 target 自变量,若有的话,采用的位置和关键字自变量获取自 args and kwargs 自变量,分别。

join ( timeout=None )

等待直到线程终止。这阻塞调用线程,直到线程的 join() 方法被调用才终止 – 正常或透过未处理异常 – 或直到发生可选超时。

timeout 自变量存在且非 None ,它应该是以秒 (或其分数) 为单位指定操作超时的浮点数。由于 join() 始终返回 None ,必须调用 is_alive() after join() 决定是否发生超时 – 若线程仍存活, join() 调用将超时。

timeout 自变量不存在或 None ,操作将阻塞,直到线程终止。

线程可以 join() 多次。

join() 引发 RuntimeError 若试图 join 当前线程,因为这会导致死锁。它也会出错当 join() 线程,在线程开始前试图这样做会引发相同异常。

名称

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

getName ( )
setName ( )

旧的 getter/setter API 为 name ;直接将其用作代替特性。

ident

此线程的 "线程标识符" 或 None 若线程尚未开始。这是非 0 整数。见 get_ident() 函数。线程标识符会被回收,当线程退出并创建另一线程时。标识符可用,即使在线程已退出后。

native_id

此线程的本机整数线程 ID。这是非负整数,或 None 若线程尚未开始。见 get_native_id() 函数。这表示线程 ID ( TID ) as assigned to the thread by the OS (kernel). Its value may be used to uniquely identify this particular thread system-wide (until the thread terminates, after which the value may be recycled by the OS).

注意

类似 PID (进程 ID),TID (线程 ID) 在线程被创建时才有效 (保证系统范围唯一),直到线程终止。

可用性 :要求 get_native_id() 函数。

3.8 版新增。

is_alive ( )

返回线程是否存活。

此方法返回 True 恰好先于 run() 方法开始直到恰好后于 run() 方法终止。模块函数 enumerate() 返回所有存活线程的列表。

daemon

A boolean value indicating whether this thread is a daemon thread (True) or not (False). This must be set before start() 被调用,否则 RuntimeError 被引发。其初始值继承自创建线程;主线程不是守护线程,因此,在主线程中创建的所有线程默认为 daemon = False .

整个 Python 程序退出,当未剩下存活的非守护线程时。

isDaemon ( )
setDaemon ( )

旧的 getter/setter API 为 daemon ;直接将其用作代替特性。

锁对象

原语锁是锁定时不属于特定线程的同步原语。在 Python 中,它目前是可用的最低级同步原语,直接实现通过 _thread 扩展模块。

原语锁处于锁定或解锁 2 种状态之一。它是在解锁状态下创建的。它拥有 2 个基本方法, acquire() and release() 。当在解锁状态时, acquire() 将状态改为锁定并立即返回。当在锁定状态时, acquire() 阻塞直到调用 release() 在另一线程中将其改为解锁,然后 acquire() 调用将它重置为锁定并返回。 release() 方法只应在锁定状态下调用;它将状态改为解锁并立即返回。若试图释放未锁定的锁, RuntimeError 会被引发。

锁还支持 上下文管理协议 .

当多个阻塞线程在 acquire() 等待状态变为解锁,仅一线程继续进行当 release() 调用将状态重置为解锁;哪个等待线程继续执行未定义,且可能因实现而异。

所有方法以原子方式执行。

class threading.

实现原语锁对象的类。一旦线程有获得锁,会阻塞后续获得尝试,直到它被释放;任何线程都可以释放它。

注意, Lock 实际是返回平台支持具体 Lock 类的最有效版本实例的工厂函数。

acquire ( blocking=True , timeout=-1 )

获得锁,阻塞或非阻塞。

当援引采用 blocking 自变量设为 True (默认),阻塞直到锁被解锁,然后将其设为锁定并返回 True .

当援引采用 blocking 自变量设为 False ,不阻塞。若调用采用 blocking 设为 True 将阻塞,返回 False 立即;否则,将锁设为锁定并返回 True .

当被援引采用浮点 timeout 自变量 (设为正值),最多阻塞秒数的指定通过 timeout 且只要无法获得锁。 timeout 自变量 -1 指定无限等待。禁止指定 timeout blocking 为 False。

返回值为 True 若成功获取锁, False 若不 (例如若 timeout 过期)。

3.2 版改变: The timeout 参数是新增的。

3.2 版改变: 通过 POSIX 信号现在可以中断锁的获取,若底层线程实现支持它。

release ( )

释放锁。可以从任何线程调用这,不仅仅是已获得锁的线程。

当锁被锁定时,将其重置为解锁并返回。若任何其它线程被阻塞等待锁变为解锁,则准确允许某一线程继续进行。

当在解锁锁援引时, RuntimeError 被引发。

没有返回值。

locked ( )

返回 True 若获得锁。

RLock 对象

可重入锁是可以被同一线程多次获得的同步原语。在内部,它使用 owning thread (拥有线程) 和 recursion level (递归级别) 概念,除原语锁使用的锁定/解锁状态外。在锁定状态下,某个线程拥有锁;在解锁状态下,没有线程拥有它。

为锁定锁,线程调用它的 acquire() 方法;这返回,一旦线程拥有锁。为解锁锁,线程调用它的 release() 方法。 acquire() / release() 调用对可以嵌套;才最后 release() ( release() 最外侧对) 将锁重置为解锁,并允许阻塞另一线程当 acquire() 以继续进行。

可重入锁还支持 上下文管理协议 .

class threading. RLock

此类实现可重入锁对象。可重入锁必须由获得它的线程释放。一旦线程获得可重入锁,同一线程可以再次获得它不阻塞;线程必须释放它一次,每次获得它时。

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

acquire ( blocking=True , timeout=-1 )

获得锁,阻塞或非阻塞。

当援引不带自变量:若此线程已经拥有锁,递归级别递增 1,并立即返回。否则,若另一线程拥有锁,阻塞直到锁被解锁。一旦锁被解锁 (不被任何线程拥有),则抓取所有权,将递归级别设为 1 并返回。若有多个线程被阻塞在等待直到锁被解锁,每次仅一个能抓取锁的所有权。在这种情况下,没有返回值。

当援引采用 blocking 自变量设为 True,做相同事情如调用不带自变量,并返回 True .

当援引采用 blocking argument set to false, do not block. If a call without an argument would block, return False 立即;否则,做相同事情如调用不带自变量,并返回 True .

当被援引采用浮点 timeout 自变量 (设为正值),最多阻塞秒数的指定通过 timeout 且只要无法获得锁。返回 True 若已获得锁,False 若超时已过。

3.2 版改变: The timeout 参数是新增的。

release ( )

释放锁,递减递归级别。若递减后为 0,将锁重置为解锁 (不被任何线程拥有),若任何其它线程被阻塞在等待锁变为解锁,仅允许它们之一继续。若递减后递归级别仍然非 0,锁依然锁定并由调用线程拥有。

才调用此方法,当调用线程拥有锁时。 RuntimeError 被引发若解锁锁时调用此方法。

没有返回值。

条件对象

条件变量始终关联某种锁;这可以传入 (或默认创建) 一个。传入一个很有用,当几个条件变量必须共享同一锁时。锁属于条件对象:不必单独追踪它。

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

必须在持有关联锁时,调用其它方法。 wait() 方法释放锁,然后阻塞,直到另一个线程唤醒它通过调用 notify() or notify_all() 。一旦被唤醒, wait() 重新获得锁并返回。此外,还可以指定超时。

The notify() 方法唤醒在等待条件变量的某一线程,若有在等待。 notify_all() 方法唤醒在等待条件变量的所有线程。

注意: notify() and notify_all() 方法不会释放锁;这意味着线程 (或被唤醒线程) 将不会返回从其 wait() 调用立即,但仅当线程调用 notify() or notify_all() 最后会放弃锁的所有权。

使用条件变量的典型编程样式,是使用锁同步访问某些共享状态;对特定状态变化感兴趣的线程会调用 wait() 重复直到它们看到期望状态,而修改状态的线程会调用 notify() or notify_all() 当它们改变状态时,以这种方式,它可能是某个等待者所期望的状态。例如,以下代码是具有不受限制缓冲容量的一般生产者/消费者情况:

# 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()
						

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

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

要选取介于 notify() and notify_all() ,考虑一种状态的改变是否只对一个或多个正等待线程感兴趣。如:在典型生产者/消费者情况下,向缓冲添加一项只需唤醒一个消费者线程。

class threading. 条件 ( lock=None )

此类实现条件变量对象。条件变量允许一个或多个线程去等待,直到由另一线程通知它们。

lock 自变量有给定且不是 None ,它必须是 Lock or RLock 对象,且它被用作底层锁。否则,新的 RLock 对象被创建并用作底层锁。

3.3 版改变: 从工厂函数变为类。

acquire ( *args )

获得底层锁。此方法调用底层锁对应方法;返回值是由相应方法返回的任何值。

release ( )

释放底层锁。此方法调用底层锁对应方法;没有返回值。

wait ( timeout=None )

等待直到被通知 (或直到发生超时)。若调用此方法时调用线程尚未获得锁, RuntimeError 被引发。

此方法释放底层锁,然后阻塞直到被唤醒由 notify() or notify_all() 调用对于在另一线程中的的相同条件变量,或直到发生可选超时为止。一旦被唤醒或超时,它重新获得锁并返回。

timeout 自变量存在且非 None ,它应该是以秒 (或其分数) 为单位指定操作超时的浮点数。

当底层锁为 RLock ,它不会被释放使用 release() 方法,由于这可能实际并未被解锁,当多次递归获得锁时。相反,内部接口的 RLock 类的使用,这真的会解锁,甚至在已递归获得几次时。然后使用另一内部接口恢复递归级别,当重新获得锁时。

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

3.2 版改变: 以前,方法总是返回 None .

wait_for ( predicate , timeout=None )

等待直到条件被评估为 True 止。 predicate 应该是其结果将被解释成布尔值的可调用。 timeout 可以提供最大给定等待时间。

此实用方法可以调用 wait() 重复直到 predicate (谓词) 被满足,或直到发生 timeout (超时)。返回值是谓词的最后返回值,并将评估为 False 若方法超时。

忽略超时特征,调用此方法大致相当于编写:

while not predicate():
    cv.wait()
						

因此,相同规则也适用于 wait() :调用时必须持有锁,而返回时重新获得锁。predicate (谓词) 在持有锁时评估。

3.2 版新增。

notify ( n=1 )

默认情况下,只唤醒等待此条件的线程 (若有的话)。若调用线程未获得锁当调用此方法时, RuntimeError 被引发。

此方法最多唤醒 n 个等待条件变量的线程;无操作若没有线程在等待。

当前实现准确唤醒 n 线程,若至少 n 线程在等待。不管怎样,依赖此行为不安全。未来,优化实现可能偶尔唤醒超过 n 线程。

注意: 被唤醒线程并不实际返回从其 wait() 调用直到它可以重新获得锁。由于 notify() 不释放锁,其调用者应释放锁。

notify_all ( )

唤醒在等待此条件的所有线程。此方法的举动像 notify() , 但唤醒所有在等待线程,而不是一个。若调用线程未获得锁当调用此方法时, RuntimeError 被引发。

信号量对象

这是计算机科学史中最古老的同步原语之一,由早期荷兰计算机科学家 Edsger W. Dijkstra 发明(他使用名称 P() and V() 而不是 acquire() and release() ).

信号量管理的内部计数器的递减是通过每 acquire() 调用和递增是通过每 release() 调用。计数器可以从不低于 0;当 acquire() 发现它为 0,阻塞,等待直到某些其它线程调用 release() .

信号量还支持 上下文管理协议 .

class threading. 信号量 ( value=1 )

此类实现信号量对象。信号量管理的原子计数器表示数 release() 调用减数 acquire() 调用,加初始值。 acquire() 方法阻塞若有必要直到它可以在不用使计数器为负的情况下返回。若不给定, value 默认为 1。

可选自变量给出初始 value 对于内部计数器;默认为 1 。若 value 给定小于 0, ValueError 被引发。

3.3 版改变: 从工厂函数变为类。

acquire ( blocking=True , timeout=None )

获得信号量。

在没有自变量的情况下援引时:

  • 若内部计数器 > 0 在进入时,递减 1 并返回 True 立即。

  • 若内部计数器为 0 在进入时,阻塞,直到被唤醒通过调用 release() 。一旦被唤醒 (且计数器大于 0),计数器递减 1 并返回 True 。正好一线程被唤醒通过每次调用 release() 。唤醒不应该依赖线程的次序。

当被援引采用 blocking set to false, do not block. If a call without an argument would block, return False 立即;否则,做相同事情如调用不带自变量,并返回 True .

当援引采用 timeout 除了 None ,它将阻塞最多 timeout 秒。若在该间隔内未成功完成获得,返回 False 。返回 True 否则。

3.2 版改变: The timeout 参数是新增的。

release ( )

Release a semaphore, incrementing the internal counter by one. When it was zero on entry and another thread is waiting for it to become larger than zero again, wake up that thread.

class threading. BoundedSemaphore ( value=1 )

实现有界信号量对象的类。有界信号量会校验,以确保其当前值不超过其初始值。若履行, ValueError 被引发。在大多数情况下,信号量用于守卫容量有限的资源。若释放信号量太多次,有 Bug 迹象。若不给定, value 默认为 1。

3.3 版改变: 从工厂函数变为类。

Semaphore 范例

信号量经常用于守卫容量有限的资源 (例如:数据库服务器)。在资源大小固定的任何情况下,都应使用有界信号量。在卵生任何工作者线程前,主线程会初始化信号量:

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

一旦卵生,工作者线程会调用信号量的获得和释放方法,当它们需要连接到服务器时:

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

使用有界信号量可以减少编程出错的机会,但会导致要多要释放的信号量,而不是获得检测。

事件对象

这是线程之间的最简单通信机制之一:一个线程发出事件信号,而其它线程等待它。

事件对象管理可以设为 True 的内部标志采用 set() 方法和重置为 False 采用 clear() 方法。 wait() 方法阻塞直到标志为 True。

class threading. 事件

实现事件对象的类。可以将事件管理标志设为 True 采用 set() 方法和重置为 False 采用 clear() 方法。 wait() 方法阻塞,直到标志为 True。标志最初为 False。

3.3 版改变: 从工厂函数变为类。

is_set ( )

返回 True 当且仅当内部标志为 True 时。

set ( )

将内部标志设为 True。在等待它的所有线程变为 True,被唤醒。线程调用 wait() 一旦标志为 True 将根本不阻塞。

clear ( )

将内部标志重置为 False。随后,线程调用 wait() 将阻塞直到 set() 被调用,再次将内部标志设为 True。

wait ( timeout=None )

阻塞,直到内部标志为 True。若进入时内部标志为 True,立即返回。否则,阻塞直到另一线程调用 set() 将标志设为 True,或直到发生可选 timeout (超时)。

当 timeout 自变量存在且非 None ,它应该是以秒 (或其分数) 为单位指定操作超时的浮点数。

此方法返回 True 当且仅当内部标志被设为 True 时,在等待调用之前或在等待开始之后,所以它总是返回 True 除了有给定 timeout (超时),且操作超时。

3.1 版改变: 以前,方法总是返回 None .

计时器对象

此类表示仅在经过一定数量时间后才应运行的动作 — 计时器。 Timer 是子类化的 Thread 因此,也可以作为创建自定义线程的范例。

就像线程,计时器的启动是通过调用它们的 start() 方法。计时器的停止 (在它的动作开始之前) 是通过调用 cancel() 方法。计时器在执行它的动作之前的等待间隔,与由用户指定的间隔可能不会准确相同。

例如:

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 )

创建计时器将运行 function 采用自变量 args 和关键词自变量 kwargs ,后于 interval 秒过去。若 args is None (默认) 那么将使用空列表。若 kwargs is None (默认) 那么将使用空字典。

3.3 版改变: 从工厂函数变为类。

cancel ( )

停止计时器,并取消计时器动作的执行。这才工作,若计时器仍处于等待阶段。

屏障对象

3.2 版新增。

此类提供简单同步原语,供需要相互等待的固定数量线程使用。每个线程会试着穿过屏障通过调用 wait() 方法并阻塞直到所有线程完成它们的 wait() 调用。此时,线程被同时释放。

可以重用屏障任意多次,对于相同数量的线程而言。

例如,这里是客户端和服务器线程的简单同步方式:

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. 屏障 ( parties , action=None , timeout=None )

创建屏障对象为 parties 数量的线程。 action ,当提供时,是释放线程时由它们中某一线程调用的可调用。 timeout 是默认超时值,若指定 None 为 wait() 方法。

wait ( timeout=None )

通过屏障。当屏障的所有线程都有调用此函数时,将同时释放它们。若 timeout 有提供,首选使用它,相比提供给类构造函数的任何。

返回值是整数在范围 0 到 parties – 1,每个线程都不同。这可以用于选择线程做一些特殊内务,如:

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

action 有提供给构造函数,某一线程会先于释放调用它。若此调用引发错误,会把屏障置于中断状态。

若调用超时,会把屏障置于中断状态。

此方法可能引发 BrokenBarrierError 异常,若屏障被中断 (或重置) 当线程在等待时。

reset ( )

返回空状态默认屏障。在等待它的任何线程将收到 BrokenBarrierError 异常。

注意,使用此函数可能要求一些外部同步,若存在状态未知的其它线程。若屏障被中断,最好还是离开它并创建一个新的屏障。

abort ( )

把屏障置于中断状态。这会导致任何活动或未来调用 wait() 失败采用 BrokenBarrierError 。例如,若某个线程需要中止,使用这能避免应用程序死锁。

更可取的是只需创建屏障采用合理 timeout 值来自动守卫某一线程的出错。

parties

要求通过屏障的线程数。

n_waiting

目前在屏障中等待的线程数。

broken

布尔为 True 若屏障处于中断状态。

exception threading. BrokenBarrierError

此异常是子类化的 RuntimeError ,被引发当 Barrier 对象被重置或中断。

使用锁、条件和信号量在 with 语句

由此模块提供的所有对象拥有 acquire() and release() 方法可以用作上下文管理器对于 with 语句。 acquire() 方法将被调用当进入块时,和 release() 将被调用当退出块时。因此,以下片段:

with some_lock:
    # do something...
			

相当于:

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

目前, Lock , RLock , Condition , Semaphore ,和 BoundedSemaphore 对象可以用作 with 语句上下文管理器。

内容表

上一话题

并发执行

下一话题

multiprocessing — 基于进程的并行

本页

版权所有  © 2014-2026 乐数软件    

工业和信息化部: 粤ICP备14079481号-1