python提供的Condition对象提供了对复杂线程同步问题的支持,使用 Condition 可以让那些己经得到 Lock 对象却无法继续执行的线程释放 Lock 对象,Condition 对象也可以唤醒其他处于等待状态的线程。
threading.Condition() 可以理解为更加高级的锁,比 Lock 和 Rlock 的用法更高级,能处理一些复杂的线程同步问题。threading.Condition() 创建一把资源锁(默认是Rlock),提供 acquire() 和 release() 方法,用法和 Rlock 一致。此外 Condition 还提供 wait()、Notify() 和 NotifyAll() 方法。
- wait():线程挂起,直到收到一个 Notify() 通知或者超时(可选参数),wait() 必须在线程得到 Rlock 后才能使用。
- acquire([timeout])/release():调用 Condition 关联的 Lock 的 acquire() 或 release() 方法。
- Notify() :在线程挂起的时候,发送一个通知,让 wait() 等待线程继续运行,Notify() 也必须在线程得到 Rlock 后才能使用。 Notify(n=1),最多唤醒 n 个线程。
- NotifyAll() :在线程挂起的时候,发送通知,让所有 wait() 阻塞的线程都继续运行。
Condition的主要使用方式
线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。
import threading,time
def A():
s.acquire()
print('赵云:看见一个敌人,请求支援')
s.wait()
print('赵云:好的')
s.notify()
s.release()
def B():
s.acquire()
print('鲁班:等我...')
s.notify()
s.wait()
print('鲁班:我到了,发起冲锋...')
if __name__=='__main__':
s = threading.Condition()
A = threading.Thread(target=A)
B = threading.Thread(target=B)
A.start()
B.start()
A.join()
B.join()
结果
赵云:看见一个敌人,请求支援
鲁班:等我...
赵云:好的
鲁班:我到了,发起冲锋...
另外:
Condition对象的构造函数可以接受一个Lock/RLock对象作为参数,如果没有指定,则Condition对象会在内部自行创建一个RLock;除了notify方法外,Condition对象还提供了notifyAll方法,可以通知waiting池中的所有线程尝试acquire内部锁。由于上述机制,处于waiting状态的线程只能通过notify方法唤醒,所以notifyAll的作用在于防止有线程永远处于沉默状态。