如何用线程与锁实现自助餐模拟?代码运行异常排查
问题分析与修复方案
你的代码存在多个核心问题,导致程序无法停止且无法进入取餐函数:
1. 死循环阻塞线程池
trail函数中的while True是无限循环,每个执行该函数的线程会持续往trail列表添加元素,永远不会终止任务。这会让第一个线程池一直处于工作状态,永远无法执行后续的取餐线程池代码。
2. 未定义变量导致取餐线程池启动失败
第二个线程池的range(1+y, number_of_meals)中,y是未定义变量,直接运行会抛出NameError,即便第一个线程池能结束,这里也无法正常启动取餐任务。
3. 线程安全漏洞
meal函数中判断x in trail和执行trail.remove(x)时,没有用trail_lock保护,多线程环境下会出现并发修改trail列表的安全问题。
修复后的代码
import threading import time import random import concurrent.futures # 模拟50个消费者 consumers = [x+1 for x in range(50)] trail = [] meal = [] # 定义锁 meal_lock = threading.Lock() trail_lock = threading.Lock() def trail(x): global trail with trail_lock: trail.append(x) print(f"消费者 {x} 获得餐位") # 模拟获取餐位的耗时 time.sleep(random.uniform(0.1, 0.5)) def meal(x): global trail, meal # 等待当前消费者获得餐位 while True: with trail_lock: if x in trail: trail.remove(x) break time.sleep(0.05) # 执行取餐逻辑 with meal_lock: meal.append(x) print(f"消费者 {x} 完成取餐") # 模拟取餐耗时 time.sleep(random.uniform(0.1, 0.5)) if __name__ == "__main__": number_of_meals = 5 number_of_trails = 5 # 先启动餐位获取线程 with concurrent.futures.ThreadPoolExecutor(max_workers=number_of_trails) as trail_executor: trail_executor.map(trail, range(number_of_trails)) # 再启动取餐线程 with concurrent.futures.ThreadPoolExecutor(max_workers=number_of_meals) as meal_executor: meal_executor.map(meal, range(number_of_meals)) print("所有模拟流程完成") print(f"已完成取餐的消费者: {meal}")
关键修复点
- 移除
trail函数的死循环,每个消费者仅执行一次获取餐位操作 - 修复取餐线程池的参数错误,使用合法的范围值
- 在
meal函数中用trail_lock保护对trail列表的所有操作,确保线程安全 - 增加模拟耗时,让流程更贴近真实自助餐场景
- 拆分线程池执行逻辑,先完成餐位获取任务再启动取餐任务(可根据业务需求调整为并行启动)
内容的提问来源于stack exchange,提问作者s005
相关产品推荐
相关产品推荐

