16.3. 线程—多个控制线程
该模块提供了用于处理多个线程(也称为“轻量级进程”或“任务”)的低级 Primitives-多个控制线程共享其全局数据空间。为了进行同步,提供了简单的锁(也称为* mutexes 或 binary semaphores *)。 threading模块提供了更易于使用的Function,并在此模块的顶部构建了更高级别的线程 API。
该模块是可选的。 Windows,Linux,SGI IRIX,Solaris 2.x 以及具有 POSIX 线程(也称为“ pthread”)实现的系统都支持该Function。对于缺少thread模块的系统,可以使用dummy_thread模块。它复制了此模块的界面,可以用作替代产品。
它定义了以下常量和函数:
-
exception
thread.
error
- 引发特定于线程的错误。
-
thread.
LockType
- 这是锁定对象的类型。
-
thread.
start_new_thread
(* function , args * [,* kwargs *])- 启动一个新线程并返回其标识符。线程执行带有参数列表* args (必须为 Tuples)的Function function 。可选的 kwargs *参数指定关键字参数的字典。当函数返回时,线程以静默方式退出。当函数以未处理的异常终止时,将打印堆栈跟踪,然后线程退出(但其他线程 continue 运行)。
-
thread.
interrupt_main
( )- 在主线程中引发KeyboardInterrupt异常。子线程可以使用此Function来break主线程。
2.3 版的新Function。
-
thread.
exit
( )- 引发SystemExitexception。如果未被捕获,这将导致线程静默退出。
-
thread.
allocate_lock
( )- 返回一个新的锁对象。锁定方法如下所述。锁最初是解锁的。
-
thread.
get_ident
( )- 返回当前线程的“线程标识符”。这是一个非零整数。它的值没有直接的意义。它旨在用作魔术 Cookies,例如为线程专用数据字典构建索引。当一个线程退出并创建另一个线程时,线程标识符可以被回收。
-
thread.
stack_size
([* size *])- 返回创建新线程时使用的线程堆栈大小。可选的* size 参数指定要用于后续创建的线程的堆栈大小,并且必须为 0(使用平台或配置的默认值)或至少 32,768(32kB)的正整数。如果未指定 size *,则使用 0.如果不支持更改线程堆栈大小,则会引发error异常。如果指定的堆栈大小无效,则会引发ValueError且堆栈大小不会被修改。当前最小支持的堆栈大小值为 32kB,以保证解释程序本身有足够的堆栈空间。请注意,某些平台可能会对堆栈大小的值有特定限制,例如要求最小堆栈大小> 32kB 或要求以系统内存页面大小的倍数进行分配-有关更多信息,请参考平台文档(常见 4kB 页面) ;在缺少更多具体信息的情况下,建议使用 4096 的倍数作为堆栈大小)。可用性:Windows,带有 POSIX 线程的系统。
2.5 版的新Function。
锁定对象具有以下方法:
-
lock.
acquire
([* waitflag *])- 如果没有可选参数,则此方法无条件获取该锁,必要时可以 await 另一线程释放该锁(一次只能有一个线程可以获取锁,这就是它们存在的原因)。如果存在整数* waitflag *参数,则该操作取决于其值:如果为零,则仅当无需 await 就可以立即获取该锁时才获取该锁,而如果它为非零,则与以前一样无条件获取该锁。如果成功获取了锁,则返回值为
True
,否则为False
。
- 如果没有可选参数,则此方法无条件获取该锁,必要时可以 await 另一线程释放该锁(一次只能有一个线程可以获取锁,这就是它们存在的原因)。如果存在整数* waitflag *参数,则该操作取决于其值:如果为零,则仅当无需 await 就可以立即获取该锁时才获取该锁,而如果它为非零,则与以前一样无条件获取该锁。如果成功获取了锁,则返回值为
-
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异常将在获取锁后发生。 -
当主线程退出时,系统定义其他线程是否存活。在使用本机线程实现的 SGI IRIX 上,它们可以生存。在大多数其他系统上,它们不执行try…finally子句或执行对象析构函数而被杀死。