Boost python /从线程导入模块需要ReleaseLock()。为啥?
Posted
技术标签:
【中文标题】Boost python /从线程导入模块需要ReleaseLock()。为啥?【英文标题】:Boost python / importing module from thread requires ReleaseLock(). Why?Boost python /从线程导入模块需要ReleaseLock()。为什么? 【发布时间】:2012-10-02 08:09:02 【问题描述】:我开发了一个带有多线程的 boost.python C/C++ 程序。
在main()
,我创建了一个线程:
PyEval_InitThreads();
pthread_create(&id, &detached_attr, newThread, NULL);
·在 newThread() 中,我调用了两个 Py_* 函数。
Py_Initialize();
PyGILState_STATE gstate = PyGILState_Ensure();
然后我在newThread()
中调用一个名为hoge()
的C++函数:
void hoge()
py::object main_module;
py::object main_namespace;
try
main_module = py::import("__main__"); //segmentation fault
main_namespace = main_module.attr("__dict__");
catch (py::error_already_set const &)
PyErr_Print();
//Some boost python code
gdb 回溯输出在这里。
(gdb) bt
#0 0x4032fe24 in __ctype_b_loc () from /lib/libc.so.6
#1 0x4032fde8 in __ctype_b_loc () from /lib/libc.so.6
为什么import()
会失败?我不知道。请告诉我如何解决这个问题。
--编辑 28 年 12 月 12 日---
我使用以下方法解决了这个问题。
在main()
,我执行
Py_Initialize();
PyEval_InitThreads();
PyEval_ReleaseLock();
然后我创建新线程。在新线程中,我执行
PyGILState_STATE gstate = PyGILState_Ensure();
CALL SOME PYTHON CODE
PyGILState_Release(gstate);
但我不知道为什么现在可以了。谁能告诉我原因?
【问题讨论】:
我建议先尝试更简单的示例。例如,尝试让代码片段在没有线程的情况下运行。一旦一切都按预期工作(测试它!)然后尝试多线程。 感谢您的建议。我可以解决这个问题。 你是怎么解决你的问题的?我有同样的问题.. 【参考方案1】:与许多其他解释语言一样,Python 通过使用全局解释器锁(或 GIL)来实现线程安全 (see this wiki),从而阻止两个 Python 解释器调用并行运行。因此,您发出的任何 python 调用都应首先请求锁,执行您的命令,然后释放锁。您必须遵循该规则,否则您可能会使解释器崩溃,就像您在示例中所做的那样。请注意,您的函数 hoge()
没有请求 GIL,因此发生了崩溃。
现在,用 GIL 请求(或“确保”)包装您的代码并释放函数调用并不能解决所有问题 - 您仍然需要确保,当您有 2 个线程时,both将有权访问 GIL。如果您不会在主线程上释放 GIL,那么实际上执行 python 内容的第二个线程将被永远阻塞!你试过吗?如果没有,你可以看看会发生什么。
正确的解决方案 - 您自己找到的解决方案是在每个线程中获取和释放 GIL,并确保您不会陷入其中一个拥有 GIL 的线程而其他线程饿死。
【讨论】:
以上是关于Boost python /从线程导入模块需要ReleaseLock()。为啥?的主要内容,如果未能解决你的问题,请参考以下文章
Python 线程内存布局(结合 boost::python)