threading
— 基于线程的并行
¶
源代码: Lib/threading.py
此模块构造更高级线程接口,基于更低级
_thread
模块。
3.7 版改变: 此模块曾经是可选的,现在始终可用。
另请参阅
concurrent.futures.ThreadPoolExecutor
提供更高级接口以将任务压入后台线程,不阻塞调用线程的执行,同时仍然能在需要时检索他们的结果。
queue
为在运行线程之间交换数据,提供线程安全接口。
asyncio
提供达成任务级并发的替代方式,不要求使用多个操作系统线程。
注意
在 Python 2.x 系列,此模块包含
camelCase
名称对于某些方法和函数。这些从 Python 3.10 起弃用,但仍支持它们为兼容 Python 2.5 及以下版本。
CPython 实现细节:
在 CPython,由于
全局解释器锁
,一次仅一线程可以执行 Python 代码 (即使某些面向性能的库可以克服此局限性)。若想让应用程序更好地利用多核机器的计算资源,建议使用
multiprocessing
or
concurrent.futures.ProcessPoolExecutor
。不管怎样,threading 仍是合适模型若想要同时运行多个 I/O 绑定任务。
可用性 :非 Emscripten,非 WASI。
本模块不工作 (或不可用) 于 WebAssembly 平台
wasm32-emscripten
and
wasm32-wasi
。见
WebAssembly 平台
了解更多信息。
此模块定义了下列函数:
返回数量为
Thread
对象的目前存活。返回计数等于列表长度,列表返回通过
enumerate()
.
函数
activeCount
是此函数的弃用别名。
返回当前
Thread
对象,对应调用者控制线程。若调用者控制线程的创建不是透过
threading
模块,返回具有有限功能的虚设线程对象。
函数
currentThread
是此函数的弃用别名。
处理未捕获异常引发通过
Thread.run()
.
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.excepthook()
。保存它以便还原原始值,若它们被损坏 (或替代) 对象所替换。
3.10 版新增。
返回当前线程的 "线程标识符"。这是非 0 整数。它的值没有直接意义;旨在作为魔法 Cookie 使用 (如:索引特定线程数据的字典)。线程标识符会被回收,当退出线程并创建另一线程时。
3.3 版新增。
返回由内核赋值的当前线程的本机整形线程 ID。这是非负整数。可以使用它的值唯一标识系统范围内的此特定线程 (直到线程终止,之后 OS 会回收该值)。
可用性 :Windows、FreeBSD、Linux、macOS、OpenBSD、NetBSD、AIX。
3.8 版新增。
返回列表为所有
Thread
对象 (目前活动)。列表包括守护线程和虚设线程对象创建通过
current_thread()
。不包括已终止线程和尚未启动的线程。不管怎样,主线程始终是结果的一部分,甚至在终止时。
为所有线程设置跟踪函数开始于
threading
模块。
func
将被传递给
sys.settrace()
为各线程,先于其
run()
方法被调用。
获取跟踪函数如设置通过
settrace()
.
3.10 版新增。
为所有线程设置 profile 函数开始于
threading
模块。
func
将被传递给
sys.setprofile()
为各线程,先于其
run()
方法被调用。
获取剖分析器函数如设置通过
setprofile()
.
3.10 版新增。
返回创建新线程时使用的线程堆栈大小。可选
size
自变量指定用于随后创建线程的堆栈大小,且必须为 0 (使用平台或配置默认的) 或至少 32,768 (32 KB) 的正整数值。若
size
未指定,使用 0。若不支持改变线程堆栈大小,
RuntimeError
被引发。若指定堆栈大小无效,
ValueError
被引发且未修改堆栈大小。32 KB 是目前支持的最小堆栈大小值,以保证解释器本身堆栈空间足够。注意,某些平台可能对堆栈大小值有特定限制,譬如要求最小堆栈大小 > 32KB 或要求按系统内存页面大小的倍数分配 - 要了解更多信息请参考平台文档编制 (4KB 页面很常见;建议堆栈大小使用 4096 的倍数方式,当缺乏更具体信息时)。
可用性 :Windows、PThreads。
支持 POSIX 线程的 Unix 平台。
此模块还定义了下列常量:
最大允许值为
timeout
参数对于阻塞函数 (
Lock.acquire()
,
RLock.acquire()
,
Condition.wait()
,等)。指定大于此值的超时将引发
OverflowError
.
3.2 版新增。
此模块定义了许多类,以下章节会详细描述。
此模块的设计基于 Java 的松散线程化模型。然而,Java 使锁和条件变量成为每个对象的基本行为,它们在 Python 中是独立对象。Python 的
Thread
类是支持 Java 线程类行为的子集;目前,没有优先级,没有线程组,线程无法被销毁、停止、挂起、恢复或中断。Java 线程类的静态方法,在实现时被映射到了模块级函数。
下文描述的所有方法都以原子方式执行。
线程局部数据是值为特定线程的数据。要管理线程局部数据,仅仅创建实例化的
local
(或子类) 并在其中存储属性:
mydata = threading.local() mydata.x = 1
实例的值异于单独线程。
表示线程局部数据的类。
对于更多细节和广泛范例,见文档编制字符串在
_threading_local
模块。
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 代码)。虚设线程对象拥有有限功能;认为它们始终存活和守护,且不可以 joined 。它们从不被删除,由于不可能检测外来线程的终止。
始终应采用关键词自变量调用此构造函数。自变量:
group
应该为
None
;预留以供未来扩展当
ThreadGroup
类被实现。
target
是要被援引的可调用对象通过
run()
方法。默认为
None
,意味着什么都不调用。
name
是线程名称。默认情况下,唯一名称构造形式为 Thread-
N
其中
N
是 小十进制数字,或 Thread-
N
(target) 其中 target 是
target.__name__
若
target
自变量有指定。
args
是用于援引目标的自变量列表 (或元组)。默认为
()
.
kwargs
是援引目标的关键词自变量字典。默认为
{}
.
若非
None
,
daemon
明确设置线程是否为守护线程。若
None
(默认),守护特性继承自当前线程。
若子类覆盖构造函数,它必须确保援引基类构造函数 (
Thread.__init__()
) 在对其它线程做任何事情之前。
3.10 版改变: 使用 target 名称若 name 自变量被省略。
3.3 版改变: 添加 daemon 自变量。
启动线程活动。
每个线程对象必须最多调用它一次。它安排对象的
run()
方法以在单独控制线程中被援引。
此方法将引发
RuntimeError
若在同一线程对象中多次调用。
表示线程活动的方法。
可以在子类中覆盖此方法。标准
run()
方法援引传递给对象构造函数的可调用对象作为
target
自变量,若有的话,采用的位置和关键字自变量获取自
args
and
kwargs
自变量,分别。
使用列表 (或元组) 作为
args
自变量传递给
Thread
可以达成相同效果。
范例:
>>> from threading import Thread >>> t = Thread(target=print, args=[1]) >>> t.run() 1 >>> t = Thread(target=print, args=(1,)) >>> t.run() 1
等待直到线程终止。这阻塞调用线程,直到线程的
join()
方法被调用才终止 – 正常或透过未处理异常 – 或直到发生可选超时。
当
timeout
自变量存在且非
None
,它应该是以秒 (或其分数) 为单位指定操作超时的浮点数。由于
join()
始终返回
None
,必须调用
is_alive()
after
join()
决定是否发生超时 – 若线程仍存活,
join()
调用将超时。
当
timeout
自变量不存在或
None
,操作将阻塞,直到线程终止。
线程可以毗连多次。
join()
引发
RuntimeError
若试图 join 当前线程,因为这会导致死锁。它也会出错当
join()
线程,在线程开始前试图这样做会引发相同异常。
仅用于标识用途的字符串。它没有语义。可以赋予多个线程相同名称。初始名称由构造函数设置。
此线程的 "线程标识符" 或
None
若线程尚未开始。这是非 0 整数。见
get_ident()
函数。线程标识符会被回收,当线程退出并创建另一线程时。标识符可用,即使在线程已退出后。
线程 ID (
TID
) 对于此线程,由 OS (内核) 赋值。这是非负整数,或
None
若线程尚未开始。见
get_native_id()
函数。此值可以用作此特定线程系统范围的唯一标识 (直到线程终止,之后值可能被 OS 回收)。
注意
类似 PID (进程 ID),TID (线程 ID) 在线程被创建时才有效 (保证系统范围唯一),直到线程终止。
可用性 :Windows、FreeBSD、Linux、macOS、OpenBSD、NetBSD、AIX、DragonFlyBSD。
3.8 版新增。
返回线程是否存活。
此方法返回
True
恰好先于
run()
方法开始直到恰好后于
run()
方法终止。模块函数
enumerate()
返回所有存活线程的列表。
布尔值指示此线程是否为守护线程 (
True
) 或不 (
False
)。必须设置这先于
start()
被调用,否则
RuntimeError
被引发。其初始值继承自创建线程;主线程不是守护线程,因此,在主线程中创建的所有线程默认为
daemon
=
False
.
整个 Python 程序退出,当未剩下存活的非守护线程时。
弃用 getter/setter API 对于
daemon
;直接将其用作代替特性。
从 3.10 版起弃用。
原语锁是锁定时不属于特定线程的同步原语。在 Python 中,它目前是可用的最低级同步原语,直接实现通过
_thread
扩展模块。
原语锁处于锁定或解锁 2 种状态之一。它是在解锁状态下创建的。它拥有 2 个基本方法,
acquire()
and
release()
。当在解锁状态时,
acquire()
将状态改为锁定并立即返回。当在锁定状态时,
acquire()
阻塞直到调用
release()
在另一线程中将其改为解锁,然后
acquire()
调用将它重置为锁定并返回。
release()
方法只应在锁定状态下调用;它将状态改为解锁并立即返回。若试图释放未锁定的锁,
RuntimeError
会被引发。
锁还支持 上下文管理协议 .
当多个阻塞线程在
acquire()
等待状态变为解锁,仅一线程继续进行当
release()
调用将状态重置为解锁;哪个等待线程继续执行未定义,且可能因实现而异。
所有方法以原子方式执行。
实现原语锁对象的类。一旦线程有获得锁,会阻塞后续获得尝试,直到它被释放;任何线程都可以释放它。
注意,
Lock
实际是返回平台支持具体 Lock 类的最有效版本实例的工厂函数。
获得锁,阻塞或非阻塞。
当援引采用
blocking
自变量设为
True
(默认),阻塞直到锁被解锁,然后将其设为锁定并返回
True
.
当援引采用
blocking
自变量设为
False
,不阻塞。若调用采用
blocking
设为
True
将阻塞,返回
False
立即;否则,将锁设为锁定并返回
True
.
当被援引采用浮点
timeout
自变量 (设为正值),最多阻塞秒数的指定通过
timeout
且只要无法获得锁。
timeout
自变量
-1
指定无限等待。禁止指定
timeout
当
blocking
is
False
.
返回值为
True
若成功获取锁,
False
若不 (例如若
timeout
过期)。
3.2 版改变: timeout 参数是新增的。
3.2 版改变: 通过 POSIX 信号现在可以中断锁的获取,若底层线程实现支持它。
释放锁。可以从任何线程调用这,不仅仅是已获得锁的线程。
当锁被锁定时,将其重置为解锁并返回。若任何其它线程被阻塞等待锁变为解锁,则准确允许某一线程继续进行。
当在解锁锁援引时,
RuntimeError
被引发。
没有返回值。
返回
True
若获得锁。
可重入锁是可以被同一线程多次获得的同步原语。在内部,它使用 owning thread (拥有线程) 和 recursion level (递归级别) 概念,除原语锁使用的锁定/解锁状态外。在锁定状态下,某个线程拥有锁;在解锁状态下,没有线程拥有它。
为锁定锁,线程调用它的
acquire()
方法;这返回,一旦线程拥有锁。为解锁锁,线程调用它的
release()
方法。
acquire()
/
release()
调用对可以嵌套;才最后
release()
(
release()
最外侧对) 将锁重置为解锁,并允许阻塞另一线程当
acquire()
以继续进行。
可重入锁还支持 上下文管理协议 .
此类实现可重入锁对象。可重入锁必须由获得它的线程释放。一旦线程获得可重入锁,同一线程可以再次获得它不阻塞;线程必须释放它一次,每次获得它时。
注意,
RLock
实际是工厂函数,返回由平台支持的具体 RLock 类的最高效版本实例。
获得锁,阻塞或非阻塞。
当援引不带自变量:若此线程已经拥有锁,递归级别递增 1,并立即返回。否则,若另一线程拥有锁,阻塞直到锁被解锁。一旦锁被解锁 (不被任何线程拥有),则抓取所有权,将递归级别设为 1 并返回。若有多个线程被阻塞在等待直到锁被解锁,每次仅一个能抓取锁的所有权。在这种情况下,没有返回值。
当援引采用
blocking
自变量设为
True
,做相同事情如调用不带自变量,并返回
True
.
当援引采用
blocking
自变量设为
False
,不阻塞。若调用不带自变量会阻塞,返回
False
立即;否则,做相同事情如调用不带自变量,并返回
True
.
当被援引采用浮点
timeout
自变量 (设为正值),最多阻塞秒数的指定通过
timeout
且只要无法获得锁。返回
True
若已获得锁,
False
若超时已过。
3.2 版改变: timeout 参数是新增的。
释放锁,递减递归级别。若递减后为 0,将锁重置为解锁 (不被任何线程拥有),若任何其它线程被阻塞在等待锁变为解锁,仅允许它们之一继续。若递减后递归级别仍然非 0,锁依然锁定并由调用线程拥有。
才调用此方法,当调用线程拥有锁时。
RuntimeError
被引发若解锁锁时调用此方法。
没有返回值。
条件变量始终关联某种锁;这可以传入 (或默认创建) 一个。传入一个很有用,当几个条件变量必须共享同一锁时。锁属于条件对象:不必单独追踪它。
条件变量遵从
上下文管理协议
:使用
with
语句可在封闭块持续时间内获得关联锁。
acquire()
and
release()
方法还调用关联锁的相应方法。
必须在持有关联锁时,调用其它方法。
wait()
方法释放锁,然后阻塞,直到另一个线程唤醒它通过调用
notify()
or
notify_all()
。一旦被唤醒,
wait()
重新获得锁并返回。此外,还可以指定超时。
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()
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()
,考虑一种状态的改变是否只对一个或多个正等待线程感兴趣。如:在典型生产者/消费者情况下,向缓冲添加一项只需唤醒一个消费者线程。
此类实现条件变量对象。条件变量允许一个或多个线程去等待,直到由另一线程通知它们。
若
lock
自变量有给定且不是
None
,它必须是
Lock
or
RLock
对象,且它被用作底层锁。否则,新的
RLock
对象被创建并用作底层锁。
3.3 版改变: 从工厂函数变为类。
获得底层锁。此方法调用底层锁对应方法;返回值是由相应方法返回的任何值。
释放底层锁。此方法调用底层锁对应方法;没有返回值。
等待直到被通知 (或直到发生超时)。若调用此方法时调用线程尚未获得锁,
RuntimeError
被引发。
此方法释放底层锁,然后阻塞直到被唤醒由
notify()
or
notify_all()
调用对于在另一线程中的的相同条件变量,或直到发生可选超时为止。一旦被唤醒或超时,它重新获得锁并返回。
当
timeout
自变量存在且非
None
,它应该是以秒 (或其分数) 为单位指定操作超时的浮点数。
当底层锁为
RLock
,它不会被释放使用
release()
方法,由于这可能实际并未被解锁,当多次递归获得锁时。相反,内部接口的
RLock
类的使用,这真的会解锁,甚至在已递归获得几次时。然后使用另一内部接口恢复递归级别,当重新获得锁时。
返回值为
True
除非给定
timeout
过期,在这种情况下为
False
.
3.2 版改变:
以前,方法总是返回
None
.
等待直到条件被评估为 True 止。 predicate 应该是其结果将被解释成布尔值的可调用。 timeout 可以提供最大给定等待时间。
此实用方法可以调用
wait()
重复直到 predicate (谓词) 被满足,或直到发生 timeout (超时)。返回值是谓词的最后返回值,并将评估为
False
若方法超时。
忽略超时特征,调用此方法大致相当于编写:
while not predicate(): cv.wait()
因此,相同规则也适用于
wait()
:调用时必须持有锁,而返回时重新获得锁。predicate (谓词) 在持有锁时评估。
3.2 版新增。
默认情况下,只唤醒等待此条件的线程 (若有的话)。若调用线程未获得锁当调用此方法时,
RuntimeError
被引发。
此方法最多唤醒 n 个等待条件变量的线程;无操作若没有线程在等待。
当前实现准确唤醒 n 线程,若至少 n 线程在等待。不管怎样,依赖此行为不安全。未来,优化实现可能偶尔唤醒超过 n 线程。
注意: 被唤醒线程并不实际返回从其
wait()
调用直到它可以重新获得锁。由于
notify()
不释放锁,其调用者应释放锁。
唤醒在等待此条件的所有线程。此方法的举动像
notify()
, 但唤醒所有在等待线程,而不是一个。若调用线程未获得锁当调用此方法时,
RuntimeError
被引发。
方法
notifyAll
是此方法的弃用别名。
这是计算机科学史中最古老的同步原语之一,由早期荷兰计算机科学家 Edsger W. Dijkstra 发明(他使用名称
P()
and
V()
而不是
acquire()
and
release()
).
信号量管理的内部计数器的递减是通过每
acquire()
调用和递增是通过每
release()
调用。计数器可以从不低于 0;当
acquire()
发现它为 0,阻塞,等待直到某些其它线程调用
release()
.
信号量还支持 上下文管理协议 .
此类实现信号量对象。信号量管理的原子计数器表示数
release()
调用减数
acquire()
调用,加初始值。
acquire()
方法阻塞若有必要直到它可以在不用使计数器为负的情况下返回。若不给定,
value
默认为 1。
可选自变量给出初始
value
对于内部计数器;默认为
1
。若
value
给定小于 0,
ValueError
被引发。
3.3 版改变: 从工厂函数变为类。
获得信号量。
在没有自变量的情况下援引时:
若内部计数器 > 0 在进入时,递减 1 并返回
True
立即。
若内部计数器为 0 在进入时,阻塞,直到被唤醒通过调用
release()
。一旦被唤醒 (且计数器大于 0),计数器递减 1 并返回
True
。正好一线程被唤醒通过每次调用
release()
。唤醒不应该依赖线程的次序。
当被援引采用
blocking
设为
False
,不阻塞。若调用不带自变量会阻塞,返回
False
立即;否则,做相同事情如调用不带自变量,并返回
True
.
当援引采用
timeout
除了
None
,它将阻塞最多
timeout
秒。若在该间隔内未成功完成获得,返回
False
。返回
True
否则。
3.2 版改变: timeout 参数是新增的。
释放信号量,将内部计数器递增 n 。当它为 0 在进入时,且其它线程在等待它再次大于 0 时,唤醒 n 线程对于这些。
3.9 版改变: 添加 n 参数以一次释放多个等待线程。
实现有界信号量对象的类。有界信号量会校验,以确保其当前值不超过其初始值。若履行,
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。
实现事件对象的类。可以将事件管理标志设为 True 采用
set()
方法和重置为 False 采用
clear()
方法。
wait()
方法阻塞,直到标志为 True。标志最初为 False。
3.3 版改变: 从工厂函数变为类。
返回
True
当且仅当内部标志为 True 时。
方法
isSet
是此方法的弃用别名。
阻塞,直到内部标志为 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
创建计时器将运行
function
采用自变量
args
和关键词自变量
kwargs
,后于
interval
秒过去。若
args
is
None
(默认) 那么将使用空列表。若
kwargs
is
None
(默认) 那么将使用空字典。
3.3 版改变: 从工厂函数变为类。
停止计时器,并取消计时器动作的执行。这才工作,若计时器仍处于等待阶段。
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)
创建屏障对象为
parties
数量的线程。
action
,当提供时,是释放线程时由它们中某一线程调用的可调用。
timeout
是默认超时值,若指定 None 为
wait()
方法。
通过屏障。当屏障的所有线程都有调用此函数时,将同时释放它们。若 timeout 有提供,首选使用它,相比提供给类构造函数的任何。
返回值是整数在范围 0 到 parties – 1,每个线程都不同。这可以用于选择线程做一些特殊内务,如:
i = barrier.wait() if i == 0: # Only one thread needs to print this print("passed the barrier")
若 action 有提供给构造函数,某一线程会先于释放调用它。若此调用引发错误,会把屏障置于中断状态。
若调用超时,会把屏障置于中断状态。
此方法可能引发
BrokenBarrierError
异常,若屏障被中断 (或重置) 当线程在等待时。
返回空状态默认屏障。在等待它的任何线程将收到
BrokenBarrierError
异常。
注意,使用此函数可能要求一些外部同步,若存在状态未知的其它线程。若屏障被中断,最好还是离开它并创建一个新的屏障。
把屏障置于中断状态。这会导致任何活动或未来调用
wait()
失败采用
BrokenBarrierError
。例如,若某个线程需要中止,使用这能避免应用程序死锁。
更可取的是只需创建屏障采用合理 timeout 值来自动守卫某一线程的出错。
要求通过屏障的线程数。
目前在屏障中等待的线程数。
布尔为
True
若屏障处于中断状态。
此异常是子类化的
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
语句上下文管理器。