SimPy如何实现替代AnyOf的互斥OneOf组件,仅允许单个进程触发
问题根因
当两个等待进程的超时时长完全相等时,两个timeout事件会被调度到SimPy同一时间点的普通优先级事件队列,AnyOf的触发回调要等当前时间点所有普通优先级事件执行完才会运行,此时两个进程都已经执行完毕,后续的中断逻辑自然不会生效。
解决方案1:自定义高优先级OneOf组件
你想要的高优先级OneOf可以直接继承SimPy的Condition类实现,核心逻辑是只要第一个事件触发,就立刻以最高优先级调度其余事件的中断操作,保证同时间点不会有第二个事件被处理:
import simpy from simpy import Condition class OneOf(Condition): def __init__(self, env, events): super().__init__(env, lambda evts: len(evts) >= 1, events) # 绑定回调,只要条件满足就立刻中断剩余事件 self.callbacks.append(self._interrupt_remaining) def _interrupt_remaining(self, _): # 拿到第一个完成的事件后,直接用最高优先级调度中断 for evt in self.events: if not evt.processed and hasattr(evt, 'interrupt'): # URGENT优先级为0,高于所有普通事件 self.env.schedule(lambda: evt.interrupt(), priority=0) # 测试代码和你原来的基本一致,只把AnyOf换成OneOf def waitingprocess(env, waitingtime): try: yield env.timeout(waitingtime) except: pass def example(env): waitingtimeA = 1.0 waitingtimeB = 1.0 A = env.process(waitingprocess(env, waitingtimeA)) B = env.process(waitingprocess(env, waitingtimeB)) events = [A,B] yield OneOf(env, events) print('is A Processed:', A.processed) print('is B Processed:', B.processed) env = simpy.Environment() Example = env.process(example(env)) env.run()
运行后输出会随机只有一个进程为True,另一个为False,符合互斥触发的要求。
解决方案2:轻量改造现有逻辑,无需自定义组件
如果不想自定义组件,也可以给等待进程加一个全局互斥标记,只要有一个进程先执行到完成逻辑,就直接阻塞另一个的结果生效:
import simpy from simpy import AnyOf mutex = False def waitingprocess(env, waitingtime): global mutex try: yield env.timeout(waitingtime) # 加互斥判断,只有第一个到达的能生效 if not mutex: mutex = True else: # 后续到达的直接抛中断模拟未处理 raise simpy.Interrupt() except: pass def example(env): global mutex mutex = False waitingtimeA = 1.0 waitingtimeB = 1.0 A = env.process(waitingprocess(env, waitingtimeA)) B = env.process(waitingprocess(env, waitingtimeB)) events = [A,B] yield AnyOf(env, events) for e in events: if not e.processed: e.interrupt() print('is A Processed:', A.processed) print('is B Processed:', B.processed) env = simpy.Environment() Example = env.process(example(env)) env.run()
内容的提问来源于stack exchange,提问作者Nick P
相关产品推荐
相关产品推荐

