一个伙夫蒸馒头(生产者,售票),要求蒸够10个,等待,并唤醒吃馒头的人
三个吃货吃馒头(消费者,买票),要求同时吃,当任何一个人发现没馒头了,唤醒伙夫。
生产者是一堆线程,消费者是另一堆线程,内存缓冲区可以使用List数组队列,数据类型只需要定义一个简单的类就好。关键是如何处理多线程之间的协作。这其实也是多线程通信的一个范例。
在这个模型中,最关键就是内存缓冲区为空的时候消费者必须等待,而内存缓冲区满的时候,生产者必须等待。其他时候可以是个动态平衡。值得注意的是多线程对临界区资源的操作时候必须保证在读写中只能存在一个线程,所以需要设计锁的策略。
import threading
import time
lock1=threading.Lock()
lock2=threading.Lock()
s1=threading.Condition(lock=lock1) # 生产锁
s2=threading.Condition(lock=lock2) #吃的锁
list=[]
mt=None
class HuoFu(threading.Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
while True:
s2.acquire() #给吃货上锁 确保只有一个吃货通知伙夫生产馒头
for i in range(1,11): #生产10个馒头
time.sleep(0.1)
list.append(i)
print(self.name,": 生产第%s个馒头"%i)
s2.notify_all() #唤醒所有的吃货
s2.release() #给吃货解锁
s1.acquire() #给伙夫上锁
s1.wait() # 让伙夫等待
s1.release()
class ChiHuo(threading.Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
while True:
s2.acquire() #因为下面有数据改变即list变化,防止并发,给吃货上锁
if len(list)==0:
# 若没有馒头 唤醒伙夫 并且让吃货等待
s1.acquire()
s1.notify()
s1.release()
s2.wait()
else:
mt=list.pop()
time.sleep(1) #让进来的吃货,休息一秒,让其他吃货进来
#print('{0}:在吃第{1}个馒头'.format(self.name, mt))
s2.release()
#在锁外面输出 不占用所得时间
if mt!=None:
print('{0}:在吃第{1}个馒头'.format(self.name, mt))
huofu=HuoFu('伙夫')
ch1=ChiHuo('jkk')
ch2=ChiHuo('98k')
ch3=ChiHuo('888')
huofu.start()
ch1.start()
ch2.start()
ch3.start()
结果:
伙夫 : 生产第1个馒头
伙夫 : 生产第2个馒头
伙夫 : 生产第3个馒头
伙夫 : 生产第4个馒头
伙夫 : 生产第5个馒头
伙夫 : 生产第6个馒头
伙夫 : 生产第7个馒头
伙夫 : 生产第8个馒头
伙夫 : 生产第9个馒头
伙夫 : 生产第10个馒头
jkk:在吃第10个馒头
98k:在吃第9个馒头
888:在吃第8个馒头
jkk:在吃第7个馒头
98k:在吃第6个馒头
888:在吃第5个馒头
jkk:在吃第4个馒头
98k:在吃第3个馒头
888:在吃第2个馒头
jkk:在吃第1个馒头
伙夫 : 生产第1个馒头
伙夫 : 生产第2个馒头
伙夫 : 生产第3个馒头
伙夫 : 生产第4个馒头
伙夫 : 生产第5个馒头
伙夫 : 生产第6个馒头
伙夫 : 生产第7个馒头
伙夫 : 生产第8个馒头
伙夫 : 生产第9个馒头
伙夫 : 生产第10个馒头
jkk:在吃第10个馒头
98k:在吃第3个馒头
888:在吃第2个馒头
jkk:在吃第9个馒头
98k:在吃第8个馒头
98k:在吃第7个馒头
jkk:在吃第6个馒头
888:在吃第5个馒头