生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例。
改问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。
生产者的主要作用是生成一定的数据放到缓冲区中,然后重复此过程;消费者也在缓冲区消耗这些数据。
该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会再缓冲区空时消耗数据。
任务说明:
- 创建一个共享区,共享区的容量为10(使用整型count变量模拟)
- 2个生产者,每个生产者消耗随机的时间单位生产1件商品并放入共享区(count自增1模拟),党共享区已满,生产者停止放入共享区,线程进入block阻塞状态,等待消费者线程唤醒。
- 5个消费者,每个消费者使用的时间单位每次从共享区获取1件商品(count自减1模拟),当共享区已空,消费者停止从共享区获取,线程进图block阻塞状态,等待生产者线程唤醒。
以下是代码实现:
count = 0
condition = threading.Condition()
# 生产者线程类
class Producer(threading.Thread):
def __init__(self, threadName):
threading.Thread.__init__(self)
self.threadName = threadName
# 重写run()方法
def run(self):
global count # 引用全局共享变量count
while True:
# 使用条件对象获取锁并锁定
if condition.acquire():
# 判断共享变量是否已达到上限(已满)
if count >= 10:
print('共享区已满,生产者Producer线程进入阻塞Block状态,停止放入!')
condition.wait() # 当前线程进入到阻塞状态
else:
count += 1 # 共享变量自增1
msg = time.ctime() + ' ' + self.threadName + '生产了1件商品放入共享区,共享区总计商品个数:'+ str(count)
print(msg)
condition.notify() # 唤醒其他阻塞状态的线程(如,消费者线程)
condition.release() # 接触锁定
time.sleep(random.randrange(10)/5) # 随机休眠N秒
# 消费者线程类
class Customer(threading.Thread):
# 重写构造方法
def __init__(self, threadName):
threading.Thread.__init__(self)
self.threadName = threadName
# 重写run()方法
def run(self):
global count # 引用全局共享变量count
while True:
# 使用条件对象获取锁并锁定
if condition.acquire():
# 判断共享变量是否已为0(已空)
if count < 1 :
print('共享区已空,消费者Customer线程进入阻塞Block状态,停止获取!')
condition.wait() # 当前线程进入到阻塞状态
else:
count -= 1 # 共享变量自减1
msg = time.ctime() + ' ' + self.threadName + '消费了1件商品,共享区总计商品个数:' + str(count)
print(msg)
condition.notify() # 唤醒其他阻塞状态的线程(如,生产者线程)
condition.release() # 接触锁定
time.sleep(random.randrange(10)) # 随机休眠N秒
pass
if __name__ == '__main__':
for i in range(2):
p = Producer('[生产者- '+ str(i + 1) + ']')
p.start()
for i in range(5):
c = Customer('[消费者- '+ str(i + 1) + ']')
c.start()
pass