子线程断点不触发是因 debugpy 默认不监听子线程,需显式配置 "subProcess": true 和 "justMyCode": false,并确保 debugpy ≥ 1.6.0;Java 虚拟线程调试卡死则因 suspendPolicy 默认为 All,须设为 "Thread"。

子线程断点不触发?不是代码问题,是 debugpy 默认不监听子线程,必须显式开启 subProcess 并配对 justMyCode。
Python 多线程断点不生效:检查 debugpy 版本和 launch.json 配置
VSCode Python 扩展默认用 debugpy,但若环境残留已弃用的 ptvsd,或 debugpy 版本低于 1.6.0,子线程断点会静默失效。调试控制台顶部日志若出现 Failed to initialize debugger 或含 ptvsd 字样,说明调试器异常。
- 运行
pip uninstall ptvsd彻底移除旧调试器 - 执行
pip install --upgrade debugpy确保 ≥ 1.6.0 - 在
.vscode/launch.json的 Python 配置中,确认包含这两项:"subProcess": true和"justMyCode": false - 修改后必须重启整个调试会话——热重载不生效
断点位置和线程上下文切换:别只盯着主线程看
即使配置正确,VSCode 也不会自动把所有线程变量堆在一起显示。它只呈现当前选中的调用栈帧对应的局部作用域。你得手动操作才能看到子线程里发生了什么。
- 断点必须打在子线程函数体第一行可执行语句上,例如
print("in thread"),而不是threading.Thread(target=...).start()那一行 - 调试暂停后,左侧
CALL STACK面板会列出MainThread、Thread-1、Thread-2等——点击任一名称,Variables面板立即切换为其局部变量 - 未暂停的线程(如卡在
time.sleep(5)中)不会出现在CALL STACK里,这是正常行为,不是 bug - 全局变量在任意线程上下文中都可见,但值是最新写入状态,注意竞态
Java 虚拟线程调试卡死:Suspend Policy 必须设为 Thread
Java 21+ 虚拟线程数量可达百万级,若调试器使用默认的 All 挂起策略,UI 会卡死甚至崩溃。这不是性能问题,是调试器策略误配。
- 在 VSCode Java 调试配置中,显式设置
"suspendPolicy": "Thread"(非默认值) - 配合条件断点过滤目标线程,例如:
thread.getName().contains("request-") && requestId == 1001 - 断点不要打在
Thread.sleep()或Object.wait()本身,而应放在其前/后一行,才能捕获有效上下文 - 阻塞调用前务必确认已持有锁(如
synchronized块内),否则断点可能被跳过
最容易被忽略的是:subProcess: true 在 Python 中启用的是“线程钩子注入”,首次命中子线程断点会有轻微延迟;Java 中 suspendPolicy: "Thread" 不仅影响响应速度,更决定你能否在多线程交互中稳定复现竞态——这两者都不是可选项,而是并发调试的启动开关。


















