一、Condition对象
1. 基本介绍
Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。
class threading.Condition(lock=None)
- 本类用于实现条件变量对象。条件变量对象允许多条线程保持等待状态直到接收另一条线程的通知。
- 如果选择传入 lock 参数,只能使用 Lock 或 RLock
对象,而且它会被当做一个隐性锁使用。如果不传此参数,那么程序会自动隐性地创建一个 RLock 对象。
acquire(*args)
- 本方法用于获取隐性锁(关联锁),它调用隐性锁的 acquire() 方法,并返回其所返回的值
release()
- 同上,本方法无返回值
wait(timeout=None)
- 等待通知或超时。如果线程没有获取到锁就调用了此方法,那么将引发 RuntimeError 异常
- 本方法会释放隐性锁,然后阻塞直到被其他线程的调用此条件变量的 notify() 或 notify_all() 唤醒,或超时。一旦被唤醒或超时,该线程将立即重新获取锁并返回
- timeout 参数是以秒为单位的浮点数
- 如果隐性锁是一个 RLock 对象,因为调用它的 release() 方法未必能够释放该锁,所以本方法会使用 RLock 对象的一个内部接口,该接口可以立即释放多重迭代的 RLock 锁。并且在需要重新获取锁的时候,也会使用一个类似的内部接口来恢复多重的迭代级别
- 本方法所阻塞的线程如果是被唤醒的,那么本方法会返回一个 True,如果是超时了,则返回 False
notify(n=1)
- 本方法默认用于唤醒处于等待本条件变量的线程。如果调用本方法的线程并没有获得锁,将引发 RuntimeError 异常
- 本方法至多可唤醒所有正在等待本条件变量的线程中的 n 个。如果调用时没有线程处于等待操作,那么本方法的调用是一个空操作
- 现在版本对本方法的实现为:在有足够多处于等待状态的线程的条件下,本方法将正好唤醒其中的 n 个,而不是像上一条中讲的“至多 n 个”。不过这种行为并不可靠。在将来,本方法很可能偶尔唤醒超过 n 条线程
notify_all()
- 唤醒正在等待本条件变量的所有线程。
2. 简单例子
# coding: utf-8
import threading
import time
def fun(cndition):
time.sleep(1) #确保先运行t2
# 获得锁
cndition.acquire()
print 'thread1 acquires lock.'
# 唤醒t2
cndition.notify()
# 进入等待状态,等待其他线程唤醒
cndition.wait()
print 'thread1 acquires lock again.'
# 释放锁
cndition.release()
def fun2(cndition):
# 获得锁
cndition.acquire()
print 'thread2 acquires lock.'
# 进入等待状态,等待其他线程唤醒
cndition.wait()
print 'thread2 acquires lock again.'
# 唤醒t1
cndition.notify()
# 释放锁
cndition.release()
if __name__ == '__main__':
cndition = threading.Condition()
t1 = threading.Thread(target=fun, args=(cndition,))
t2 = threading.Thread(target=fun2, args=(cndition,))
t1.start()
t2.start()
运行效果:
thread2 acquires lock.
thread1 acquires lock.
thread2 acquires lock again.
thread1 acquires lock again.