操作系统生产者和消费者python3实现

来源:互联网 发布:linux ant下载安装 编辑:程序博客网 时间:2024/06/07 03:15

【一】生产者和消费者实现原理


简易思维导图

这里写图片描述

1.问题背景:避免进程之间出现临界资源的互斥访问的死锁现象
2.解决方式:记录型信号量机制
3.具体细节
- mutex:互斥信号量,初始值是1
- empty:判空信号量
- full:判满信号量
- array[n]:缓冲池存放产品
4.实现好处: 解决死锁


【二】实现细节设计:

  1. 缓存池:循环队列 in,out标记队头和队尾
    利用in,out指针实现加减操作放入拿出产品
    in:指向当前最后产品的存储空间(队位,放入)(rear)
    out:指向最早放入产品存储空间(队头,拿取)(head)
    具体生产者:生产者生产产品,in=(in+1)%n记录更新位置
    具体消费者:消费者拿取产品,out=(out+1)%n记录更新位置

  2. 互斥信号量:初始值为1,保证临界资源的互斥性
    3.代码构建:
    对象 消费者和生产者 调用
    循环队列 (阻塞队列)缓冲池
    4.代码实现:

①基本队列内容编写

class Queue(object):# 定义队列类    def __init__(self,size):       self.size = size #定义队列长度       self.queue = []#存储队列 列表    #返回对象的字符串表达式 方便调试    def __str__(self):        return str(self.queue)#什么含义    #初始化队列    #def init(self):    #入队    def inQueue(self,n):        if self.isFull():            return -1        self.queue.append(n)#列表末尾添加新的对象    #出队    def outQueue(self):        if self.isEmpty():            return -1        firstElement = self.queue[0]  #删除队头元素        self.queue.remove(firstElement) #删除队操作        return firstElement    #删除某元素    def delete(self,n,m):        self.queue[n] = m    #插入某元素    def inPut(self,n,m):#n代表列表当前的第n位元素 m代表传入的值        self.queue[n] = m    #获取当前长度    def getSize(self):        return len(self.queue)    #判空    def isEmpty(self):        if len(self.queue)==0:            return True        return False    #判满    def isFull(self):        if len(self.queue) == self.size:            return True        return False#if __name__ == '__main__':#如何使用?queueTest = Queue(10)for i in range(10):    queueTest.inQueue(i)print('列表元素',queueTest)print('列表长度',queueTest.getSize())print('判空',queueTest.isEmpty())print('判满',queueTest.isFull())queueTest.inPut(1,20)#list【0】 = 2queueTest.outQueue()#出队print('当前列表',queueTest)结果:列表元素 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]列表长度 10判空 False判满 True当前列表 [20, 2, 3, 4, 5, 6, 7, 8, 9]

②生产者消费者代码具体实现

#全局变量实现头尾指针动态指向内容ii = 0head = 0rear = 0mutex = 1#互斥信号量  初始为1标志当前队列有无被占用flag =1 #标志初始化#消费者class Customer():    def __init__(self):        print('>>>消费者请求访问仓库')    def opreate(self,customer):        if flag ==1:  #如何使队列只能创建一个对象  全局            customer.init()#列表越界很可能就是列表越界        global  mutex  # 创建队列对象 以便队列操作        if mutex == -1:            return print('>>>缓冲区当前正有人操作,消费者不能操作')        else:            mutex = mutex - 1            if (customer.isEmpty())== True:                print('>>>当前缓冲区为空,消费者不能取用产品')                if input('是否调用生产者提供补给(输入1-YES|0-NO) ')=='1':                    print('>>>调用生产者')                    mutex = mutex+1                    product=Producer()                    product.opreate(customer)                else:                    mutex = mutex + 1                    return print('>>>拒绝提醒,消费者继续等待')            else:                customer.outPut() #其中包含head的操作                print('消费者取用产品完毕,当前产品队列从', head, '到', rear, '处依然存有产品','缓存队列',customer)                mutex =mutex+1 #操作完毕互斥量恢复class Producer():    def __init__(self):        print('>>>生产者请求访问缓存区')    def opreate(self,producer):        if flag == 1:            producer.init()  #重复初始化 傻瓜式不影响        print(producer)        global  mutex        if mutex == -1:            return print('>>>缓冲区当前繁忙,生产者不能进行操作')        else:            mutex = mutex-1            if producer.isFully() == True:                print('>>>缓冲区为满,生产者不能放入产品')                if input('是否调用消费者进行消耗(输入1-YES|0-NO) ') == 1:                    print('>>>调用消费者')                    mutex = mutex+1                    customer=Customer()                    customer.operate(CirQueue())                else:                    mutex = mutex + 1                    return print('>>>拒绝提醒,生产者继续等待')            else:                producer.inPut('产品')                mutex = mutex + 1                print('>>>生产者生产产品完毕,当前产品队列从', head, '到', rear-1, '处依然存有产品','缓存队列',producer)class CirQueue():#循环队列队头取元素 队末尾插入元素   #可加可不加object 报错ndentationError: expected an indented block  为什么?    def __init__(self):        self.size =11#队列固定长度        self.Queue=[]#队列以列表形式定义        global head,rear,i        head = 0#存储头队列元素 用于消费者删除        rear = 0#存储尾队列元素 用于生产者放入    def __str__(self):        return str(self.Queue)    def init(self):#初始化 头尾标志依旧指向首位        self.Queue=[0,0,0,0,0,0,0,0,0,0,0]#傻瓜式初始化        global flag        flag = 0    # 判空    def isEmpty(self):       j = 0       # print('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', j)       count = 0       while j != 10:  # 将10个元素全部遍历           if self.Queue[j] == 0:               count = count + 1  # 记录元素为空的元素个数           j = j + 1       if count == 10:           return True       return False    # 判满    def isFully(self):       j = 0       # print('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', j)       count = 0       while j != 10:  # 将10个元素全部遍历           if self.Queue[j] == 0:               count = count + 1  # 记录元素为空的元素个数           j = j + 1       if count == 0:           return True       return False    #队尾插入元素    def inPut(self,n):#n代表插入的元素        global rear        print(self.Queue)        #print('aaaaaaaaaaaaaaa', rear)        #print('aaaaaaaaaaaaaaa', rear)        if rear == 10:#判满操作不符合循环            return print('队列已满')        else:            i= rear            while self.Queue[i]!=0:                i=i+1            if i==11:#判断 空 元素值全为0                rear = 0                #self.rear=0#正常队尾插入元素操作            elif i>0|i<10:#中间元素不为空                rear=i            elif i==10:#空                return print( '队列已满')        self.Queue[rear]=n #插入元素n        rear = rear+1    #队头取元素    def outPut(self):        global head        j=0        count =0        while j!=10:#将10个元素全部遍历            if self.Queue[j] ==0:                count = count+1#记录元素为空的元素个数            j =j+1        if count == 10:#列表里为空            return print('列表为空不能取元素')        else:            i =head            while self.Queue[i]!=0:                i=i+1            head = i            self.Queue[head] = 0  # 赋值0 ---清除元素操作"""测试内容:test = CirQueue()#满队列不能放入实现test.init()#初始化 11个0print(test)for i in range(10):#操作放满缓冲区10个元素    test.inPut('产品')print(test)print('aaaaaaaaaaaaaaa',rear)test.inPut(1)#期待此操作过后出现 报满提示#空队列不能拿出test.init()test.outPut()#期待空元素 报空提示print(test)"""#队列初始化test = CirQueue()test.init()#初始化 11个0print(test)#消费者访问缓冲区拿元素cus0 = Customer()cus0.opreate(test)#期待结果是  消费者判断当前缓存队列为空  调用生产者生产  放入一个产品print('ssssssssssssssssssssssss',test)pro0 = Producer()pro0.opreate(test)print(test)pro1 = Producer()pro1.opreate(test)print(test)"""结果:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>>消费者请求访问仓库>>>当前缓冲区为空,消费者不能取用产品是否调用生产者提供补给(输入1-YES|0-NO) 1>>>调用生产者>>>生产者请求访问缓存区[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0][0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>>生产者生产产品完毕,当前产品队列从 0 到 0 处依然存有产品 缓存队列 ['产品', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]ssssssssssssssssssssssss ['产品', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>>生产者请求访问缓存区['产品', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]['产品', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]>>>生产者生产产品完毕,当前产品队列从 0 到 1 处依然存有产品 缓存队列 ['产品', '产品', 0, 0, 0, 0, 0, 0, 0, 0, 0]['产品', '产品', 0, 0, 0, 0, 0, 0, 0, 0, 0]>>>生产者请求访问缓存区['产品', '产品', 0, 0, 0, 0, 0, 0, 0, 0, 0]['产品', '产品', 0, 0, 0, 0, 0, 0, 0, 0, 0]>>>生产者生产产品完毕,当前产品队列从 0 到 2 处依然存有产品 缓存队列 ['产品', '产品', '产品', 0, 0, 0, 0, 0, 0, 0, 0]['产品', '产品', '产品', 0, 0, 0, 0, 0, 0, 0, 0]Process finished with exit code""""""测试内容:#放入10个产品test = CirQueue()test.init()for i in range(10):    test.inPut('产品')    print(test)"""
阅读全文
0 0
原创粉丝点击