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

C++使用std::async异步调用嵌入Python代码触发资源死锁问题求解

报错原因分析

可能的触发原因

  • Python解释器多线程调用不规范:CPython 本身不是线程安全的,你当前在每个异步任务里独立调用Py_Initialize()和Py_Finalize(),反复初始化、销毁解释器实例的行为属于未定义操作,如果两个异步任务同时执行Python相关逻辑,会直接触发解释器内部的GIL、资源锁竞争,刚好对应你收到的Resource deadlock avoided错误。
  • 全局Python对象无同步保护:你定义了全局的python结构体存储Python对象指针,多个异步任务并发运行时会同时修改、读写这些指针,很容易出现野指针访问、对象提前释放的问题,也会触发底层异常。
  • std::future 析构阻塞引发死锁:你每次给全局的tasks.myTask赋值新的std::async返回值时,旧的future会自动析构,如果旧的任务还未执行完成,future析构会主动阻塞等待任务结束,此时如果任务内部执行Python逻辑时在等待锁资源,主线程又在阻塞等待future析构,就会触发死锁判定抛出异常。
  • Python模块访问内部锁冲突:你每次执行任务都重新导入Python模块、获取函数指针,PyObject_GetAttrString调用时如果有其他线程也在操作同一个模块对象,Python内部的导入锁、对象访问锁会出现竞争,也会引发死锁。

修复建议

  • 把Py_Initialize()和Py_Finalize()移到程序启动、退出阶段的主线程执行,全局仅初始化、销毁一次解释器,不要在异步任务里反复调用。
  • 初始化Python解释器后开启多线程支持:Python 3.9以下版本调用PyEval_InitThreads(),后续子线程调用Python API前主动获取GIL,调用完成后释放GIL,不要跨线程传递未管理引用计数的Python对象。
  • 移除全局的python结构体,每个任务用到的Python对象都定义为局部变量,用完后主动调用Py_DECREF减少引用计数,避免多任务共享Python对象指针。
  • 给CallTask函数加互斥锁,避免多个线程同时操作全局的tasks.myTask出现并发读写冲突。
  • 增加空指针判定逻辑:PyImport_Import、PyObject_GetAttrString等调用后都要检查返回值是否为空,避免空指针访问引发崩溃。

内容的提问来源于stack exchange,提问作者Jordy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 10:24:03