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()。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

从boost python模块中的pyside导入类?

Python 线程内存布局(结合 boost::python)

python3怎么导入re模块

python第五天:协程,匿名函数,递归函数,模块导入,re模块

如何从.so文件导入python模块?

python 导入re模块语法及规则