问题描述:
系统中由多个生产者进程和多个消费者进程,共享一个能存放10件产品的环形缓冲区(初始值为空)。当缓冲区未满时,生产者进程可以放入其生产的一件产品,否则等待;当缓冲区未空时,消费者进程可以从缓冲区取走一件产品,否则等待。要求一个消费者进程从缓冲区连续取出3件产品后,其他消费者进程才可以取产品。
import random
import threading
import time
empty=threading.Semaphore(10) # 创建信号量empty表示可以防止产品的位置,并赋初值为10
full=threading.Semaphore(0) # 被占满的空(物品)的信号量
mutex=threading.Event() # 生产者与消费者互斥信号量
mutex1=threading.Event() # 消费者之间互斥信号量
#lock=threading.Lock();
mutex.set() #设标志为True
mutex1.set()
def producer():
global empty,mutex,lock,full
i=1
while(i<=15): # 控制生产者执行次数
empty.acquire() # 容量empty减去1
mutex.clear() # mutex设置为False,其他线程等待
print("生产!" + str(i))
i+=1
mutex.set() # mutex设置为True, 其它线程可以使用
full.release() # 物品数full加1
time.sleep(random.random())
def consumer():
global empty, mutex, lock, full
i=1
while(i<=15):
mutex1.clear() #消费者间互斥
for j in range(1,4): #连续取走三个产品
full.acquire() #取走产品,full加1
mutex.clear()
print("消费!"+str(i)+"-"+str(j))
i+=1
mutex.set()
empty.release()
time.sleep(random.random())
mutex1.set() # 三次取物品结束后才释放mutex1,其他消费者在三次执行完之前,等待...
if __name__ =='__main__':
producer=threading.Thread(name='Producer',target=producer)
consumer=threading.Thread(name='Consumer',target=consumer)
#启动线程
producer.start()
consumer.start()
运行结果:
总结:
此问题与普通的生产者与消费者问题差别在于,要求一个消费者从缓冲区连续取走3件产品后,其他消费者才可以取产品,所以消费者之间又存在了互斥的关系,在一个消费者执行完三次取操作之前,其他消费着不能来干扰,所以可以在设置一个控制消费者之间进行互斥的信号量mutex1,当一个消费者p(mutex1)后,此信号量的值为0,或者为false,其他消费者在第一个消费者执行完三次取操作之前,如果想要取产品,就会被阻塞,因此实现了消费者之间的互斥。