16.3. thread — 多线程控制 — Python 文档
16.3. 线 — 多线程控制
笔记
thread 模块已在 Python 3 中重命名为 _thread
。 2to3 工具将在将您的源代码转换为 Python 3 时自动调整导入; 但是,您应该考虑使用高级 threading 模块。
该模块提供用于处理多线程(也称为 轻量级进程 或 任务 )的低级原语——多个控制线程共享其全局数据空间。 对于同步,提供了简单的锁(也称为 互斥锁 或 二进制信号量 )。 threading 模块提供了一个更易于使用的高级线程 API,该 API 构建在该模块之上。
该模块是可选的。 它在 Windows、Linux、SGI IRIX、Solaris 2.x 以及具有 POSIX 线程(又名 “pthread”)实现。 对于缺少 thread 模块的系统,可以使用 dummy_thread 模块。 它复制了这个模块的接口,可以用作替代品。
它定义了以下常量和函数:
- exception thread.error
- 引发线程特定的错误。
- thread.LockType
- 这是锁对象的类型。
- thread.start_new_thread(function, args[, kwargs])
- 启动一个新线程并返回其标识符。 线程使用参数列表 args(必须是元组)执行函数 function。 可选的 kwargs 参数指定关键字参数的字典。 当函数返回时,线程默默退出。 当函数因未处理的异常而终止时,会打印堆栈跟踪,然后线程退出(但其他线程继续运行)。
- thread.interrupt_main()
在主线程中引发
KeyboardInterrupt
异常。 子线程可以使用这个函数来中断主线程。2.3 版中的新功能。
- thread.exit()
- 引发
SystemExit
异常。 如果没有被捕获,这将导致线程静默退出。
- thread.allocate_lock()
- 返回一个新的锁对象。 下面描述了锁的方法。 锁最初是解锁的。
- thread.get_ident()
- 返回当前线程的“线程标识符”。 这是一个非零整数。 它的价值没有直接的意义; 它旨在用作魔术饼干,例如 索引线程特定数据的字典。 当一个线程退出并创建另一个线程时,线程标识符可能会被回收。
- thread.stack_size([size])
返回创建新线程时使用的线程堆栈大小。 可选的 size 参数指定用于后续创建的线程的堆栈大小,并且必须为 0(使用平台或配置的默认值)或至少为 32,768 (32kB) 的正整数值。 如果未指定 size,则使用 0。 如果不支持更改线程堆栈大小,则会引发 错误 异常。 如果指定的堆栈大小无效,则会引发
ValueError
并且堆栈大小未修改。 32kB 是当前支持的最小堆栈大小值,以保证解释器本身有足够的堆栈空间。 请注意,某些平台可能对堆栈大小的值有特定限制,例如要求最小堆栈大小 > 32kB 或要求以系统内存页面大小的倍数进行分配 - 应参考平台文档以获取更多信息(4kB 页面很常见) ;如果没有更具体的信息,建议使用 4096 的倍数作为堆栈大小)。 可用性:Windows,具有 POSIX 线程的系统。2.5 版中的新功能。
锁对象有以下方法:
- lock.acquire([waitflag])
- 如果没有可选参数,此方法将无条件地获取锁,如有必要,等待它被另一个线程释放(一次只有一个线程可以获取锁——这就是它们存在的原因)。 如果存在整数 waitflag 参数,则操作取决于其值:如果为零,则仅在无需等待即可立即获取时才获取锁,如果不为零,则获取锁像以前一样无条件。 获取锁成功返回值为
True
,否则返回值为False
。
- 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
异常将被任意线程接收。 (当 signal 模块可用时,中断总是转到主线程。)调用 sys.exit() 或引发
SystemExit
异常相当于调用 thread.exit()。不可能在锁上中断
acquire()
方法——KeyboardInterrupt
异常将在获取锁后发生。当主线程退出时,它不会执行任何通常的清理(除了 try ... finally 子句被遵守),并且标准 I/O 文件不会被刷新。