You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用线程与锁实现自助餐模拟?代码运行异常排查

问题分析与修复方案

你的代码存在多个核心问题,导致程序无法停止且无法进入取餐函数:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 16:50:43