Python轮转调度(Round Robin)模拟异常输出问题:Job3到达时间不符合预期
Python轮转调度(Round Robin)模拟异常输出问题:Job3到达时间不符合预期
嘿,我仔细看了你的代码和问题,核心问题出在事件处理的时机不对——你的代码没有在每次时间推进后及时检查新到达的作业和完成的I/O任务,导致J3的到达被延迟检测了。
问题根源拆解
- J3到达检测延迟:当上下文切换把
current_time从1推进到2时,你的代码没有立刻调用update_ready_queue()来检查J3(到达时间2),而是直接执行J2的时间片,把current_time跳到3,直到下一次循环开头才触发作业到达检查,这就导致J3的到达日志晚了1个时间单位。 - I/O任务处理不及时:原代码只在循环开头处理I/O,时间跳变后没有及时检查I/O是否完成,比如J3本该在2+2=4完成I/O,但因为被延迟到3才加入I/O队列,实际完成时间变成了5。
修复方案
核心思路是:每次current_time发生变化后,必须立即检查新到达的作业和完成的I/O任务,不能等到下一次循环开头才处理。具体要修改这几个地方:
- 在上下文切换完成后,立刻调用
update_ready_queue()和process_io(); - 在执行完CPU时间片后,立刻调用这两个函数;
- 在CPU idle时间推进后,同样立刻调用这两个函数;
- 确保作业到达检查的逻辑能覆盖当前时间点的所有新作业。
修改后的完整代码
jobs = [ {"name": "J1", "arrival": 0, "burst": [1, 5, 2], "type": ["CPU", "IO", "CPU"], "completion_time": None}, {"name": "J2", "arrival": 1, "burst": [1, 2], "type": ["CPU", "CPU"], "completion_time": None}, {"name": "J3", "arrival": 2, "burst": [2, 1], "type": ["IO", "CPU"], "completion_time": None}, ] # Variables for simulation current_time = 0 ready_queue = [] # Jobs ready for CPU execution io_queue = [] # Jobs in I/O phase with (job, start_time) completed_jobs = 0 context_switch = 1 # Time for context switch quantum = 1 # Time quantum for Round Robin first = False # Event log for debugging event_log = [] arrived_jobs = set() # Track jobs that have already had their arrival logged def log_event(time, event): """Log events for debugging.""" event_log.append(f"Time {time}: {event}") def update_ready_queue(): """Update ready queue based on job arrival.""" for job in jobs: # Check if the job arrived if job["arrival"] <= current_time and job["name"] not in arrived_jobs: arrived_jobs.add(job["name"]) # Mark job as having arrived log_event(current_time, f"{job['name']} arrived") # If job is starting with CPU burst, add to ready queue if job["type"][0] == "CPU": ready_queue.append(job) log_event(current_time, f"{job['name']} added to ready queue") # If job is starting with I/O burst, add to I/O queue if job["type"][0] == "IO": io_queue.append((job, current_time)) log_event(current_time, f"{job['name']} moved to I/O queue") def process_io(): """Process jobs in the I/O queue.""" global completed_jobs # 遍历副本避免修改列表时出错 for job, start_time in list(io_queue): elapsed_time = current_time - start_time io_burst_time = job["burst"][0] if elapsed_time >= io_burst_time: # I/O burst completed io_queue.remove((job, start_time)) job["burst"].pop(0) job["type"].pop(0) if job["burst"]: if job["type"][0] == "CPU": ready_queue.append(job) log_event(current_time, f"{job['name']} completed I/O and added to ready queue") else: job["completion_time"] = current_time completed_jobs += 1 log_event(current_time, f"{job['name']} completed") previous_job = None while completed_jobs < len(jobs): # 先处理当前时间点的到达和I/O完成事件 update_ready_queue() process_io() if ready_queue: current_job = ready_queue.pop(0) # 处理上下文切换 if first and previous_job != current_job: current_time += context_switch log_event(current_time, "Context switch") # 上下文切换后时间变化,立即检查新事件 update_ready_queue() process_io() # 执行CPU时间片 burst_time_left = current_job["burst"][0] time_to_execute = min(burst_time_left, quantum) current_job["burst"][0] -= time_to_execute current_time += time_to_execute log_event(current_time, f"{current_job['name']} executed for {time_to_execute} time units") # 执行完时间片后,立即检查新事件 update_ready_queue() process_io() # 处理作业后续状态 if current_job["burst"][0] == 0: current_job["burst"].pop(0) current_job["type"].pop(0) if current_job["burst"]: if current_job["type"][0] == "IO": io_queue.append((current_job, current_time)) log_event(current_time, f"{current_job['name']} moved to I/O") else: current_job["completion_time"] = current_time completed_jobs += 1 log_event(current_time, f"{current_job['name']} completed") # 如果作业还有CPU burst,放回就绪队列 if current_job["burst"] and current_job["type"][0] == "CPU": ready_queue.append(current_job) log_event(current_time, f"{current_job['name']} added back to ready queue") previous_job = current_job first = True else: # CPU空闲,时间推进1 log_event(current_time, "CPU idle") current_time += 1 # 时间推进后立即检查新事件 update_ready_queue() process_io() # Output print("\n".join(event_log)) completion_times = {job["name"]: job["completion_time"] for job in jobs} print("Completion Times:", completion_times)
修复后的效果
现在J3会在Time2被正确检测到并加入I/O队列,I/O完成时间变成2+2=4,整体执行流程更符合Round Robin的规则。运行后你会看到J3的到达日志正确出现在Time2,核心问题已经解决。
备注:内容来源于stack exchange,提问作者Ace
相关产品推荐
相关产品推荐

