条件对象
条件对象总是与某种类型的锁对象相关联,锁对象可以通过传入获得,或者在缺省的情况下自动创建。
threading.Condition(lock=None)
实现条件对象的类。它具有如下方法:
acquire(*args):请求底层锁。
release():释放底层锁。
wait(timeout=None):等待直到被通知或发生超时。
wait_for(predicate, timeout=None):等待直到条件计算为 True,predicate 是一个可调用对象且它的返回值可被解释为一个布尔值。
notify(n=1):默认唤醒一个等待该条件的线程。
notify_all():唤醒所有正在等待该条件的线程。
使用条件对象的典型场景是将锁用于同步某些共享状态的权限,那些关注某些特定状态改变的线程重复调用 wait() 方法,直到所期望的改变发生;对于修改状态的线程,它们将当前状态改变为可能是等待者所期待的新状态后,调用 notify() 方法或者 notify_all() 方法。
import time import threading # 创建条件对象 c = threading.Condition() privilege = 0 def getPri(): global privilege c.acquire() c.wait() print(privilege) c.release() def updPri(): time.sleep(5) c.acquire() global privilege privilege = 1 c.notify() c.release() if __name__ == '__main__': t1 = threading.Thread(target=getPri) t2 = threading.Thread(target=updPri) t1.start() t2.start()
信号量对象
和锁机制一样,信号量机制也是一种实现线程同步的机制,不过它比锁多了一个计数器,这个计数器主要用来计算当前剩余的锁的数量。
threading.Semaphore(value=1)
信号量实现类,可选参数 value 赋予内部计数器初始值,默认值为 1 。它具有如下方法:
- acquire(blocking=True, timeout=None):获取一个信号量,参数 blocking 用来设置是否阻塞,timeout 用来设置阻塞时间。
- release():释放一个信号量,将内部计数器的值增加1。
import threading # 创建信号量对象 s = threading.Semaphore(10) a = 5 def oper(b): # 获取信号量 s.acquire() global a a = a - b a = a + b # 释放信号量 s.release() def target(b): for i in range(100000): oper(b) if __name__ == '__main__': m = 5 while m > 0: t1 = threading.Thread(target=target, args=(1,)) t2 = threading.Thread(target=target, args=(2,)) t1.start() t2.start() t1.join() t2.join() print(a) m = m - 1
事件对象
一个线程发出事件信号,其他线程等待该信号,这是最简单的线程之间通信机制之一。
threading.Event
实现事件对象的类。它有如下方法:
- is_set():当内部标志为 True 时返回 True。
- set():将内部标志设置为 True。
- clear():将内部标志设置为 False。
- wait(timeout=None):阻塞线程直到内部变量为 True。
import time import threading # 创建事件对象 event = threading.Event() def dis_class(): time.sleep(5) event.wait() print('同学们下课了') def bell(): time.sleep(3) print('下课铃声响了') event.set() if __name__ == '__main__': t1 = threading.Thread(target=bell) t2 = threading.Thread(target=dis_class) t1.start() t2.start() t1.join() t2.join()