''' 所谓条件变量,即这种机制是在满足了特定的条件后,线程才可以访问相关的数据。 它使用Condition类来完成,由于它也可以像锁机制那样用,所以它也有acquire方法和release方法,而且它还有wait,notify,notifyAll方法。 一个简单的生产消费者模型,通过条件变量的控制产品数量的增减,调用一次生产者产品就是+1,调用一次消费者产品就会-1. 使用 Condition 类来完成,由于它也可以像锁机制那样用,所以它也有 acquire 方法和 release 方法,而且它还有 wait, notify, notifyAll 方法。 ''' import threading import queue, time, random # 产品类 class Goods: def __init__(self): self.count = 0 def add(self, num=1): self.count += num def sub(self): if self.count >= 0: self.count -= 1 def empty(self): return self.count <= 0 # 生产者 class Producer(threading.Thread): def __init__(self, condition, goods, sleeptime=1): threading.Thread.__init__(self) self.cond = condition self.goods = goods self.sleeptime = sleeptime def run(self): cond = self.cond goods = self.goods while True: # 锁住资源 cond.acquire() goods.add() print("产品数量:", goods.count, "生产者线程") # 唤醒所有等待的线程 -> 其实就是唤醒消费者进程 cond.notifyAll() # 解锁资源 cond.release() time.sleep(self.sleeptime) # 消费者 class Consumer(threading.Thread): def __init__(self, condition, goods, sleeptime=2): threading.Thread.__init__(self) self.cond = condition self.goods = goods self.sleeptime = sleeptime def run(self): cond = self.cond goods = self.goods while True: time.sleep(self.sleeptime) # 锁住资源 cond.acquire() # 如无产品则让线程等待 while goods.empty(): cond.wait() goods.sub() print("产品数量:", goods.count, "消费者线程") # 解锁资源
cond.release()
g = Goods() c = threading.Condition() pro = Producer(c, g) pro.start() con = Consumer(c, g) con.start()
''' event 对象最好单次使用,就是说,你创建一个 event 对象,让某个线程等待这个对象, 一旦这个对象被设置为真,你就应该丢弃它。尽管可以通过 clear() 方法来重置 event 对 象,但是很难确保安全地清理 event 对象并对它重新赋值。很可能会发生错过事件、死锁 或者其他问题(特别是,你无法保证重置 event 对象的代码会在线程再次等待这个 event对象之前执行)。如果一个线程需要不停地重复使用 event 对象,你最好使用 Condition 对象来代替。下面的代码使用 Condition 对象实现了一个周期定时器,每当定时器超时的 时候,其他线程都可以监测到: ''' import threading import time class PeriodicTimer: def __init__(self, interval): self._interval = interval self._flag = 0 self._cv = threading.Condition() def start(self): t = threading.Thread(target=self.run) t.daemon = False t.start() def run(self): # Run the timer and notify waiting threads after each interval while True: time.sleep(self._interval) with self._cv: self._flag ^= 1 self._cv.notify_all() def wait_for_tick(self): # wait for the next tick of the timer with self._cv: last_flag = self._flag while last_flag == self._flag: self._cv.wait() ptimer = PeriodicTimer(2) ptimer.start() def countdown(nticks): while nticks > 0: ptimer.wait_for_tick() print('T-minus', nticks) nticks -= 1 def countup(last): n = 0 while n < last: ptimer.wait_for_tick() print('Counting', n) n += 1 threading.Thread(target=countdown, args=(10,)).start() threading.Thread(target=countup, args=(10,)).start()