C++ 解释Python扩展多线程

C++ 解释Python扩展多线程,c++,python,multithreading,boost-python,C++,Python,Multithreading,Boost Python,Python解释器有一个全局解释器锁,据我所知,扩展必须在多线程环境中获得它。但表示扩展功能必须释放GIL,并在退出时重新获取它 我不想在这里猜测,所以我想知道在以下场景中GIL锁定模式应该是什么: 从python调用扩展(可能在python线程中运行) 扩展的后台线程调用Py.*函数 最后一个问题是,为什么链接文档说应该释放并重新获取GIL?每当Python解释字节码时,GIL都由当前运行的线程持有。在获得GIL之前,其他Python线程都无法运行 当解释器调用本机代码时,该代码有两个关于GI

Python解释器有一个全局解释器锁,据我所知,扩展必须在多线程环境中获得它。但表示扩展功能必须释放GIL,并在退出时重新获取它

我不想在这里猜测,所以我想知道在以下场景中GIL锁定模式应该是什么:

  • 从python调用扩展(可能在python线程中运行)
  • 扩展的后台线程调用
    Py.*
    函数

  • 最后一个问题是,为什么链接文档说应该释放并重新获取GIL?

    每当Python解释字节码时,GIL都由当前运行的线程持有。在获得GIL之前,其他Python线程都无法运行

    当解释器调用本机代码时,该代码有两个关于GIL的选项:

  • 它什么也做不了
  • 它可以在工作时释放GIL,然后在返回Python之前重新获取它
  • 如果本机代码多次调用Python的运行时,那么应该选择选项1:除非持有GIL,否则永远无法安全地调用Python的运行时(只有少数例外情况,例如如果没有GIL,则调用获取GIL)

    如果本机代码做了大量的工作,但没有以任何方式涉及到Python,那么您可以使用选项2:一旦发布GIL,Python将能够调度另一个Python线程,从而获得一些并行性。如果不释放GIL,那么在Boost代码运行时,Python的其他线程都不能执行:这就是为什么文档告诉您释放并重新获取GIL

    如果您这样做,那么在释放GIL之前或重新获取GIL之后,必须小心地使您能够访问所有的
    Py.*
    功能。这可能意味着您必须制作数据的本地副本,因为在GIL发布时,您无法安全地访问Python数据类型,如列表或字典元素


    如果您的Boost代码需要在GIL被释放时回调到Python中,那么您需要获取GIL,进行调用,释放GIL。尽量避免从非Python创建的线程中进行此类调用,因为它们需要额外的工作才能获得GIL。

    谢谢,这样就可以解决问题了。然而,最后一件事需要澄清:当Python代码调用本机扩展代码时,它可以选择释放GIL。但是调用本机代码时,callstack包含对Python函数的调用,如
    PyObject\u CallFunction
    PyObject\u Call
    。为什么在这些函数的上下文中释放GIL是安全的?这些函数在堆栈展开并“返回”到之前不会“做”任何事情。到那时,你应该已经重新获得GIL,这样他们就可以工作了。