生产者/消费者"/>
python 生产者/消费者
线程在系统中运行时,线程的调度具有一定的透明性,通常程序无法准确预知线程的轮换执行,Python 可通过线程通信来保证线程协调运行。
假设系统中有两个线程,这两个线程分别代表存款者和取钱者,现在假设系统有一种特殊的要求,即要求存款者和取钱者不断地重复存款、取钱的动作,而且要求每当存款者将钱存入指定账户后,取钱者就立即取出该笔钱。不允许存款者连续两次存钱,也不允许取钱者连续两次取钱。
为了实现这种功能,可以借助于 Condition 对象来保持协调。使用 Condition 可以让那些己经得到 Lock 对象却无法继续执行的线程释放 Lock 对象,Condition 对象也可以唤醒其他处于等待状态的线程。
Condition 类提供了如下几个方法:
acquire([timeout])/release():调用 Condition 关联的 Lock 的 acquire() 或 release() 方法。
wait([timeout]):使当前线程进入 Condition 的等待池等待通知并释放锁,直到其他线程调用该 Condition 的 notify() 或 notify_all() 方法来唤醒该线程。在调用该 wait() 方法时可传入一个 timeout 参数,指定该线程最多等待多少秒。
notify():唤醒在该 Condition 等待池中的单个线程并通知它,收到通知的线程将自动调用
notify_all():唤醒在该 Condition 等待池中等待的所有线程并通知它们。
acquire() 方法尝试加锁。如果所有线程都在该 Condition 等待池中等待,则会选择唤醒其中一个线程,选择是任意性的。
实现代码如下:
import threading
import time class Account:def __init__(self,balance):self._balance = balance # 旗标 控制应该那个线程工作# False 表示存钱,True 表示取钱self._flag = False self._cond = threading.Condition() def draw(self,amount):while True:self._cond.acquire()if self._flag:time.sleep(0.01)self._balance -= amount print(threading.current_thread(),'draw++',self._balance)self._flag = False self._cond.notify_all() self._cond.wait() else:print(threading.current_thread(),'draw--',self._balance)self._cond.wait() def deposit(self,amount):while True:self._cond.acquire()if not self._flag:time.sleep(0.01)self._balance += amountprint(threading.current_thread(),'deposit++',self._balance)self._flag = True self._cond.notify_all() self._cond.wait() else:print(threading.current_thread(),'deposit--',self._balance)self._cond.wait()a = Account(0)threading.Thread(target=a.draw,args=(100,)).start()
threading.Thread(target=a.deposit,args=(100,)).start()
效果如下:存钱、取钱交替执行,threading.Condition 对象的wait() 方法会释放当前线程的锁,并让当前线程进入阻塞状态,故可以不需要调用release() 释放锁。如果先调用wait(),再notify_all() 方法将会导致程序死锁。
更多推荐
python 生产者/消费者
发布评论