16.2. threading
— Higher-level threading interface¶
源代码: Lib/threading.py
This module constructs higher-level threading interfaces on top of the lower
level thread
module.
See also the mutex
and Queue
modules.
The dummy_threading
module is provided for situations where
threading
cannot be used because thread
is missing.
注解
Starting with Python 2.6, this module provides PEP 8 compliant aliases and
properties to replace the camelCase
names that were inspired by Java’s
threading API. This updated API is compatible with that of the
multiprocessing
module. However, no schedule has been set for the
deprecation of the camelCase
names and they remain fully supported in
both Python 2.x and 3.x.
注解
Starting with Python 2.5, several Thread methods raise RuntimeError
instead of AssertionError
if called erroneously.
CPython implementation detail: In CPython, due to the Global Interpreter Lock, only one thread
can execute Python code at once (even though certain performance-oriented
libraries might overcome this limitation).
If you want your application to make better use of the computational
resources of multi-core machines, you are advised to use
multiprocessing
. However, threading is still an appropriate model
if you want to run multiple I/O-bound tasks simultaneously.
This module defines the following functions and objects:
-
threading.
active_count
()¶ -
threading.
activeCount
()¶ 返回当前存活的线程类
Thread
对象。返回的计数等于enumerate()
返回的列表长度。在 2.6 版更改: Added
active_count()
spelling.
-
threading.
Condition
() A factory function that returns a new condition variable object. A condition variable allows one or more threads to wait until they are notified by another thread.
See 条件对象.
-
threading.
current_thread
()¶ -
threading.
currentThread
()¶ 返回当前对应调用者的控制线程的
Thread
对象。如果调用者的控制线程不是利用threading
创建,会返回一个功能受限的虚拟线程对象。在 2.6 版更改: Added
current_thread()
spelling.
-
threading.
enumerate
()¶ 以列表形式返回当前所有存活的
Thread
对象。 该列表包含守护线程,current_thread()
创建的虚拟线程对象和主线程。它不包含已终结的线程和尚未开始的线程。
-
threading.
Event
() A factory function that returns a new event object. An event manages a flag that can be set to true with the
set()
method and reset to false with theclear()
method. Thewait()
method blocks until the flag is true.See 事件对象.
-
class
threading.
local
¶ A class that represents thread-local data. Thread-local data are data whose values are thread specific. To manage thread-local data, just create an instance of
local
(or a subclass) and store attributes on it:mydata = threading.local() mydata.x = 1
在不同的线程中,实例的值会不同。
更多相关细节和大量示例,参见
_threading_local
模块的文档。2.4 新版功能.
-
threading.
Lock
()¶ A factory function that returns a new primitive lock object. Once a thread has acquired it, subsequent attempts to acquire it block, until it is released; any thread may release it.
See 锁对象.
-
threading.
RLock
()¶ A factory function that returns a new reentrant lock object. A reentrant lock must be released by the thread that acquired it. Once a thread has acquired a reentrant lock, the same thread may acquire it again without blocking; the thread must release it once for each time it has acquired it.
See 递归锁对象.
-
threading.
Semaphore
([value]) A factory function that returns a new semaphore object. A semaphore manages a counter representing the number of
release()
calls minus the number ofacquire()
calls, plus an initial value. Theacquire()
method blocks if necessary until it can return without making the counter negative. If not given, value defaults to 1.See 信号量对象.
-
threading.
BoundedSemaphore
([value])¶ A factory function that returns a new bounded semaphore object. A bounded semaphore checks to make sure its current value doesn’t exceed its initial value. If it does,
ValueError
is raised. In most situations semaphores are used to guard resources with limited capacity. If the semaphore is released too many times it’s a sign of a bug. If not given, value defaults to 1.
-
class
threading.
Thread
A class that represents a thread of control. This class can be safely subclassed in a limited fashion.
See 线程对象.
-
class
threading.
Timer
A thread that executes a function after a specified interval has passed.
See 定时器对象.
-
threading.
settrace
(func)¶ 为所有
threading
模块开始的线程设置追踪函数。在每个线程的run()
方法被调用前,func 会被传递给sys.settrace()
。2.3 新版功能.
-
threading.
setprofile
(func)¶ 为所有
threading
模块开始的线程设置性能测试函数。在每个线程的run()
方法被调用前,func 会被传递给sys.setprofile()
。2.3 新版功能.
-
threading.
stack_size
([size])¶ Return the thread stack size used when creating new threads. The optional size argument specifies the stack size to be used for subsequently created threads, and must be 0 (use platform or configured default) or a positive integer value of at least 32,768 (32 KiB). If size is not specified, 0 is used. If changing the thread stack size is unsupported, a
ThreadError
is raised. If the specified stack size is invalid, aValueError
is raised and the stack size is unmodified. 32kB is currently the minimum supported stack size value to guarantee sufficient stack space for the interpreter itself. Note that some platforms may have particular restrictions on values for the stack size, such as requiring a minimum stack size > 32kB or requiring allocation in multiples of the system memory page size - platform documentation should be referred to for more information (4kB pages are common; using multiples of 4096 for the stack size is the suggested approach in the absence of more specific information). Availability: Windows, systems with POSIX threads.2.5 新版功能.
-
exception
threading.
ThreadError
¶ Raised for various threading-related errors as described below. Note that many interfaces use
RuntimeError
instead ofThreadError
.
Detailed interfaces for the objects are documented below.
该模块的设计基于 Java的线程模型。 但是,在Java里面,锁和条件变量是每个对象的基础特性,而在Python里面,这些被独立成了单独的对象。 Python 的 Thread
类只是 Java 的 Thread 类的一个子集;目前还没有优先级,没有线程组,线程还不能被销毁、停止、暂停、恢复或中断。 Java 的 Thread 类的静态方法在实现时会映射为模块级函数。
下列描述的方法都是自动执行的。
16.2.1. 线程对象¶
This class represents an activity that is run in a separate thread of control.
There are two ways to specify the activity: by passing a callable object to the
constructor, or by overriding the run()
method in a subclass. No other
methods (except for the constructor) should be overridden in a subclass. In
other words, only override the __init__()
and run()
methods of
this class.
Once a thread object is created, its activity must be started by calling the
thread’s start()
method. This invokes the run()
method in a
separate thread of control.
Once the thread’s activity is started, the thread is considered ‘alive’. It
stops being alive when its run()
method terminates – either normally, or
by raising an unhandled exception. The is_alive()
method tests whether the
thread is alive.
Other threads can call a thread’s join()
method. This blocks the calling
thread until the thread whose join()
method is called is terminated.
A thread has a name. The name can be passed to the constructor, and read or
changed through the name
attribute.
A thread can be flagged as a “daemon thread”. The significance of this flag is
that the entire Python program exits when only daemon threads are left. The
initial value is inherited from the creating thread. The flag can be set
through the daemon
property.
注解
守护线程在程序关闭时会突然关闭。他们的资源(例如已经打开的文档,数据库事务等等)可能没有被正确释放。如果你想你的线程正常停止,设置他们成为非守护模式并且使用合适的信号机制,例如: Event
。
有个 “主线程” 对象;这对应Python程序里面初始的控制线程。它不是一个守护线程。
There is the possibility that “dummy thread objects” are created. These are
thread objects corresponding to “alien threads”, which are threads of control
started outside the threading module, such as directly from C code. Dummy
thread objects have limited functionality; they are always considered alive and
daemonic, and cannot be join()
ed. They are never deleted, since it is
impossible to detect the termination of alien threads.
-
class
threading.
Thread
(group=None, target=None, name=None, args=(), kwargs={})¶ 调用这个构造函数时,必需带有关键字参数。参数如下:
group 应该为
None
;为了日后扩展ThreadGroup
类实现而保留。target 是用于
run()
方法调用的可调用对象。默认是None
,表示不需要调用任何方法。name 是线程名称。默认情况下,由 “Thread-N” 格式构成一个唯一的名称,其中 N 是小的十进制数。
args 是用于调用目标函数的参数元组。默认是
()
。kwargs 是用于调用目标函数的关键字参数字典。默认是
{}
。如果子类型重载了构造函数,它一定要确保在做任何事前,先发起调用基类构造器(
Thread.__init__()
)。-
start
()¶ 开始线程活动。
It must be called at most once per thread object. It arranges for the object’s
run()
method to be invoked in a separate thread of control.如果同一个线程对象中调用这个方法的次数大于一次,会抛出
RuntimeError
。
-
run
()¶ 代表线程活动的方法。
You may override this method in a subclass. The standard
run()
method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.
-
join
([timeout])¶ Wait until the thread terminates. This blocks the calling thread until the thread whose
join()
method is called terminates – either normally or through an unhandled exception – or until the optional timeout occurs.When the timeout argument is present and not
None
, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). Asjoin()
always returnsNone
, you must callisAlive()
afterjoin()
to decide whether a timeout happened – if the thread is still alive, thejoin()
call timed out.当 timeout 参数不存在或者是
None
,这个操作会阻塞直到线程终结。A thread can be
join()
ed many times.join()
raises aRuntimeError
if an attempt is made to join the current thread as that would cause a deadlock. It is also an error tojoin()
a thread before it has been started and attempts to do so raises the same exception.
-
name
¶ 只用于识别的字符串。它没有语义。多个线程可以赋予相同的名称。 初始名称由构造函数设置。
2.6 新版功能.
-
ident
¶ The ‘thread identifier’ of this thread or
None
if the thread has not been started. This is a nonzero integer. See thethread.get_ident()
function. Thread identifiers may be recycled when a thread exits and another thread is created. The identifier is available even after the thread has exited.2.6 新版功能.
-
is_alive
()¶ -
isAlive
()¶ 返回线程是否存活。
This method returns
True
just before therun()
method starts until just after therun()
method terminates. The module functionenumerate()
returns a list of all alive threads.在 2.6 版更改: Added
is_alive()
spelling.
-
daemon
¶ A boolean value indicating whether this thread is a daemon thread (True) or not (False). This must be set before
start()
is called, otherwiseRuntimeError
is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and therefore all threads created in the main thread default todaemon
=False
.当没有存活的非守护线程时,整个Python程序才会退出。
2.6 新版功能.
-
16.2.2. 锁对象¶
A primitive lock is a synchronization primitive that is not owned by a
particular thread when locked. In Python, it is currently the lowest level
synchronization primitive available, implemented directly by the thread
extension module.
A primitive lock is in one of two states, “locked” or “unlocked”. It is created
in the unlocked state. It has two basic methods, acquire()
and
release()
. When the state is unlocked, acquire()
changes the state
to locked and returns immediately. When the state is locked, acquire()
blocks until a call to release()
in another thread changes it to unlocked,
then the acquire()
call resets it to locked and returns. The
release()
method should only be called in the locked state; it changes the
state to unlocked and returns immediately. If an attempt is made to release an
unlocked lock, a ThreadError
will be raised.
When more than one thread is blocked in acquire()
waiting for the state to
turn to unlocked, only one thread proceeds when a release()
call resets
the state to unlocked; which one of the waiting threads proceeds is not defined,
and may vary across implementations.
所有方法都是自动执行的。
-
Lock.
acquire
([blocking])¶ 可以阻塞或非阻塞地获得锁。
当调用时参数 blocking 设置为
True
(缺省值),阻塞直到锁被释放,然后将锁锁定并返回True
。在参数 blocking 被设置为
False
的情况下调用,将不会发生阻塞。如果调用时 blocking 设为True
会阻塞,并立即返回False
;否则,将锁锁定并返回True
。
-
Lock.
release
()¶ Release a lock.
当锁被锁定,将它重置为未锁定,并返回。如果其他线程正在等待这个锁解锁而被阻塞,只允许其中一个允许。
When invoked on an unlocked lock, a
ThreadError
is raised.没有返回值。
16.2.3. 递归锁对象¶
重入锁是一个可以被同一个线程多次获取的同步基元组件。在内部,它在基元锁的锁定/非锁定状态上附加了 “所属线程” 和 “递归等级” 的概念。在锁定状态下,某些线程拥有锁 ; 在非锁定状态下, 没有线程拥有它。
To lock the lock, a thread calls its acquire()
method; this returns once
the thread owns the lock. To unlock the lock, a thread calls its
release()
method. acquire()
/release()
call pairs may be
nested; only the final release()
(the release()
of the outermost
pair) resets the lock to unlocked and allows another thread blocked in
acquire()
to proceed.
-
RLock.
acquire
([blocking=1])¶ 可以阻塞或非阻塞地获得锁。
当无参数调用时: 如果这个线程已经拥有锁,递归级别增加一,并立即返回。否则,如果其他线程拥有该锁,则阻塞至该锁解锁。一旦锁被解锁(不属于任何线程),则抢夺所有权,设置递归等级为一,并返回。如果多个线程被阻塞,等待锁被解锁,一次只有一个线程能抢到锁的所有权。在这种情况下,没有返回值。
当调用时参数 blocking 设置为
True
,和没带参数调用一样做同样的事,然后返回True
。当 blocking 参数设置为 false 的情况下调用,不进行阻塞。如果一个无参数的调用已经阻塞,立即返回false;否则,执行和无参数调用一样的操作,并返回true。
-
RLock.
release
()¶ 释放锁,自减递归等级。如果减到零,则将锁重置为非锁定状态(不被任何线程拥有),并且,如果其他线程正被阻塞着等待锁被解锁,则仅允许其中一个线程继续。如果自减后,递归等级仍然不是零,则锁保持锁定,仍由调用线程拥有。
只有当前线程拥有锁才能调用这个方法。如果锁被释放后调用这个方法,会引起
RuntimeError
异常。没有返回值。
16.2.4. 条件对象¶
A condition variable is always associated with some kind of lock; this can be passed in or one will be created by default. (Passing one in is useful when several condition variables must share the same lock.)
A condition variable has acquire()
and release()
methods that call
the corresponding methods of the associated lock. It also has a wait()
method, and notify()
and notifyAll()
methods. These three must only
be called when the calling thread has acquired the lock, otherwise a
RuntimeError
is raised.
The wait()
method releases the lock, and then blocks until it is awakened
by a notify()
or notifyAll()
call for the same condition variable in
another thread. Once awakened, it re-acquires the lock and returns. It is also
possible to specify a timeout.
The notify()
method wakes up one of the threads waiting for the condition
variable, if any are waiting. The notifyAll()
method wakes up all threads
waiting for the condition variable.
Note: the notify()
and notifyAll()
methods don’t release the lock;
this means that the thread or threads awakened will not return from their
wait()
call immediately, but only when the thread that called
notify()
or notifyAll()
finally relinquishes ownership of the lock.
Tip: the typical programming style using condition variables uses the lock to
synchronize access to some shared state; threads that are interested in a
particular change of state call wait()
repeatedly until they see the
desired state, while threads that modify the state call notify()
or
notifyAll()
when they change the state in such a way that it could
possibly be a desired state for one of the waiters. For example, the following
code is a generic producer-consumer situation with unlimited buffer capacity:
# Consume one item
cv.acquire()
while not an_item_is_available():
cv.wait()
get_an_available_item()
cv.release()
# Produce one item
cv.acquire()
make_an_item_available()
cv.notify()
cv.release()
To choose between notify()
and notifyAll()
, consider whether one
state change can be interesting for only one or several waiting threads. E.g.
in a typical producer-consumer situation, adding one item to the buffer only
needs to wake up one consumer thread.
-
class
threading.
Condition
([lock])¶ 如果给出了非
None
的 lock 参数,则它必须为Lock
或者RLock
对象,并且它将被用作底层锁。否则,将会创建新的RLock
对象,并将其用作底层锁。-
acquire
(*args)¶ 请求底层锁。此方法调用底层锁的相应方法,返回值是底层锁相应方法的返回值。
-
release
()¶ 释放底层锁。此方法调用底层锁的相应方法。没有返回值。
-
wait
([timeout])¶ 等待直到被通知或发生超时。如果线程在调用此方法时没有获得锁,将会引发
RuntimeError
异常。This method releases the underlying lock, and then blocks until it is awakened by a
notify()
ornotifyAll()
call for the same condition variable in another thread, or until the optional timeout occurs. Once awakened or timed out, it re-acquires the lock and returns.当提供了 timeout 参数且不是
None
时,它应该是一个浮点数,代表操作的超时时间,以秒为单位(可以为小数)。当底层锁是个
RLock
,不会使用它的release()
方法释放锁,因为当它被递归多次获取时,实际上可能无法解锁。相反,使用了RLock
类的内部接口,即使多次递归获取它也能解锁它。 然后,在重新获取锁时,使用另一个内部接口来恢复递归级别。
-
notify
(n=1)¶ 默认唤醒一个等待这个条件的线程。如果调用线程在没有获得锁的情况下调用这个方法,会引发
RuntimeError
异常。这个方法唤醒最多 n 个正在等待这个条件变量的线程;如果没有线程在等待,这是一个空操作。
当前实现中,如果至少有 n 个线程正在等待,准确唤醒 n 个线程。但是依赖这个行为并不安全。未来,优化的实现有时会唤醒超过 n 个线程。
注意:被唤醒的线程实际上不会返回它调用的
wait()
,直到它可以重新获得锁。因为notify()
不会释放锁,只有它的调用者应该这样做。
-
notify_all
()¶ -
notifyAll
()¶ 唤醒所有正在等待这个条件的线程。这个方法行为与
notify()
相似,但并不只唤醒单一线程,而是唤醒所有等待线程。如果调用线程在调用这个方法时没有获得锁,会引发RuntimeError
异常。在 2.6 版更改: Added
notify_all()
spelling.
-
16.2.5. 信号量对象¶
This is one of the oldest synchronization primitives in the history of computer
science, invented by the early Dutch computer scientist Edsger W. Dijkstra (he
used P()
and V()
instead of acquire()
and release()
).
A semaphore manages an internal counter which is decremented by each
acquire()
call and incremented by each release()
call. The counter
can never go below zero; when acquire()
finds that it is zero, it blocks,
waiting until some other thread calls release()
.
-
class
threading.
Semaphore
([value])¶ 可选参数 value 赋予内部计数器初始值,默认值为
1
。如果 value 被赋予小于0的值,将会引发ValueError
异常。-
acquire
([blocking])¶ 获取一个信号量。
When invoked without arguments: if the internal counter is larger than zero on entry, decrement it by one and return immediately. If it is zero on entry, block, waiting until some other thread has called
release()
to make it larger than zero. This is done with proper interlocking so that if multipleacquire()
calls are blocked,release()
will wake exactly one of them up. The implementation may pick one at random, so the order in which blocked threads are awakened should not be relied on. There is no return value in this case.When invoked with blocking set to true, do the same thing as when called without arguments, and return true.
在参数 blocking 被设置为false的情况下调用,将不会发生阻塞。如果不带参数的调用会发生阻塞的话,带参数的调用在相同情况下将会立即返回false。否则,执行和不带参数的调用一样的操作并返回true。
-
release
()¶ 释放一个信号量,将内部计数器的值增加1。当计数器原先的值为0且有其它线程正在等待它再次大于0时,唤醒正在等待的线程。
-
16.2.5.1. Semaphore
例子¶
信号量通常用于保护数量有限的资源,例如数据库服务器。在资源数量固定的任何情况下,都应该使用有界信号量。在生成任何工作线程前,应该在主线程中初始化信号量。
maxconnections = 5
...
pool_sema = BoundedSemaphore(value=maxconnections)
工作线程生成后,当需要连接服务器时,这些线程将调用信号量的 acquire 和 release 方法:
pool_sema.acquire()
conn = connectdb()
... use connection ...
conn.close()
pool_sema.release()
使用有界信号量能减少这种编程错误:信号量的释放次数多于其请求次数。
16.2.6. 事件对象¶
这是线程之间通信的最简单机制之一:一个线程发出事件信号,而其他线程等待该信号。
一个事件对象管理一个内部标志,调用 set()
方法可将其设置为true,调用 clear()
方法可将其设置为false,调用 wait()
方法将进入阻塞直到标志为true。
-
class
threading.
Event
¶ The internal flag is initially false.
-
wait
([timeout])¶ 阻塞线程直到内部变量为true。如果调用时内部标志为true,将立即返回。否则将阻塞线程,直到调用
set()
方法将标志设置为true或者发生可选的超时。当提供了timeout参数且不是
None
时,它应该是一个浮点数,代表操作的超时时间,以秒为单位(可以为小数)。This method returns the internal flag on exit, so it will always return
True
except if a timeout is given and the operation times out.在 2.7 版更改: 很明显,方法总是返回
None
。
-
16.2.7. 定时器对象¶
此类表示一个操作应该在等待一定的时间之后运行 — 相当于一个定时器。 Timer
类是 Thread
类的子类,因此可以像一个自定义线程一样工作。
与线程一样,通过调用 start()
方法启动定时器。而 cancel()
方法可以停止计时器(在计时结束前), 定时器在执行其操作之前等待的时间间隔可能与用户指定的时间间隔不完全相同。
例如:
def hello():
print "hello, world"
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
16.2.8. Using locks, conditions, and semaphores in the with
statement¶
All of the objects provided by this module that have acquire()
and
release()
methods can be used as context managers for a with
statement. The acquire()
method will be called when the block is entered,
and release()
will be called when the block is exited.
Currently, Lock
, RLock
, Condition
,
Semaphore
, and BoundedSemaphore
objects may be used as
with
statement context managers. For example:
import threading
some_rlock = threading.RLock()
with some_rlock:
print "some_rlock is locked while this executes"
16.2.9. Importing in threaded code¶
While the import machinery is thread-safe, there are two key restrictions on threaded imports due to inherent limitations in the way that thread-safety is provided:
- Firstly, other than in the main module, an import should not have the side effect of spawning a new thread and then waiting for that thread in any way. Failing to abide by this restriction can lead to a deadlock if the spawned thread directly or indirectly attempts to import a module.
- Secondly, all import attempts must be completed before the interpreter starts shutting itself down. This can be most easily achieved by only performing imports from non-daemon threads created through the threading module. Daemon threads and threads created directly with the thread module will require some other form of synchronization to ensure they do not attempt imports after system shutdown has commenced. Failure to abide by this restriction will lead to intermittent exceptions and crashes during interpreter shutdown (as the late imports attempt to access machinery which is no longer in a valid state).