Simpy离散事件模拟中维修人员资源请求异常占用问题求解
Simpy离散事件模拟维修环节死锁问题解决方案
问题根因
你当前逻辑的死锁来源于资源请求和条件判断的顺序错误:
- 调用
self.repairman.request()并执行yield request_repair之后,Simpy会直接将该维修人员标记为占用状态,self.repairman.count会加1 - 你后续的while循环判断条件包含
self.repairman.count==self.num_repairman,当所有维修人员都被你的请求占用后,该条件永远成立,程序陷入无限等待 - 额外的逻辑问题:你将顾客置换流程和产品维修流程绑定在同一个进程中,不符合实际业务逻辑,维修应该是独立于顾客到店的后台持续流程。
修复方案
1. 架构调整
单独启动一个后台维修进程,循环检测坏产品库存,只要有坏产品且有空闲维修人员就触发维修,不需要和顾客流程绑定,也能正确记录维修人员队列数据。
2. 资源请求逻辑调整
如果需要保留当前绑定逻辑的写法,调整请求和判断的顺序:先发起资源请求(此时请求会进入队列,len(self.repairman.queue)会正确更新,满足你记录队列数据的需求),先判断所有前置条件满足后,再yield等待资源分配,拿到资源后直接执行维修。
3. 代码bug修复
- 修正导入语句:
import simpy而非import simply - 在
__init__方法中初始化self.lost_customers = 0,避免属性不存在报错 - 移除while循环中冗余的维修人员可用判断,资源请求本身就会等待空闲维修人员
可运行的修正后代码
import simpy class Store(object): def __init__(self, env, num_cashiers, num_repairman): self.env = env self.num_cashiers = num_cashiers self.num_repairman = num_repairman self.cashiers = simpy.Resource(env, capacity=num_cashiers) self.repairman = simpy.Resource(env, capacity=num_repairman) self.total_customers = 0 self.lost_customers = 0 self.broken_product = 0 self.repaired_product = 25 self.resource_data = [] # 启动后台维修进程 env.process(self.repair_daemon()) def customer_generator(self, env): customer_buffer = 5 product_id = 1 customer_interarrival_time = 100 while True: if len(self.cashiers.queue) >= customer_buffer: self.lost_customers +=1 else: env.process(self.store_operations(env, product_id)) yield env.timeout(customer_interarrival_time) product_id+=1 self.total_customers +=1 def serve_customer(self, product_id): yield self.env.timeout(90) self.broken_product +=1 self.repaired_product -=1 def repair_product(self, product_id): yield self.env.timeout(300) self.broken_product -=1 self.repaired_product +=1 def repair_daemon(self): # 后台维修进程,独立处理所有坏产品 product_id = 0 while True: # 等待有坏产品 while self.broken_product == 0: yield self.env.timeout(1) # 发起维修人员请求,此时队列数据会正确更新 request_repair = self.repairman.request() yield request_repair # 拿到资源直接维修 product_id +=1 yield self.env.process(self.repair_product(product_id)) self.repairman.release(request_repair) # 记录数据 self.resource_data.append({ 'time' : self.env.now, 'broken product inv' : self.broken_product, 'repaired product inv': self.repaired_product, 'busy cashiers' : self.cashiers.count, 'cashier queue' : len(self.cashiers.queue), 'busy repairmen' : self.repairman.count, 'repairmen queue' : len(self.repairman.queue) }) def store_operations(self, env, product_id): # 顾客置换流程 request_cashier = self.cashiers.request() yield request_cashier # 等待有可用的修复产品 while self.repaired_product == 0: yield env.timeout(1) # 执行顾客服务 yield env.process(self.serve_customer(product_id)) self.cashiers.release(request_cashier) return if __name__ == "__main__": env = simpy.Environment() store1 = Store(env, 3, 3) env.process(store1.customer_generator(env)) env.run(500) # 输出记录数据 for i in range(min(7, len(store1.resource_data))): print(store1.resource_data[i])
内容的提问来源于stack exchange,提问作者Boblo
相关产品推荐
相关产品推荐

