Python GIL和线程 我在我的C++应用程序中嵌入了Python 3。Python为用户提供了自定义数据处理的脚本功能。 问题:我有许多与Python交互的线程,我真的不知道如何使用GIL保护我的代码。到目前为止,我使代码工作的唯一方法是使用boost::mutex

Python GIL和线程 我在我的C++应用程序中嵌入了Python 3。Python为用户提供了自定义数据处理的脚本功能。 问题:我有许多与Python交互的线程,我真的不知道如何使用GIL保护我的代码。到目前为止,我使代码工作的唯一方法是使用boost::mutex,c++,python-3.x,python-c-api,gil,C++,Python 3.x,Python C Api,Gil,下面是一个非常简单的例子,再现了我的问题: 线程A首先调用Init()来初始化Python(静态函数) 线程B调用Pythonize()。线程B在第一次调用锁定GIL时被阻塞 代码: #包括 #包括 #包括 #包括“Python.h” 结构RTMaps_GILLock { RTMaps_GILLock() { std::cout我遇到了您的问题,请确保不要从主线程调用PyGILState_sure(),主线程是初始化python的线程,因为它需要完全不同的调用。 我已经设置了一个线程映射器,

下面是一个非常简单的例子,再现了我的问题:

  • 线程A首先调用
    Init()
    来初始化Python(静态函数)
  • 线程B调用
    Pythonize()。线程B在第一次调用锁定GIL时被阻塞
代码:

#包括
#包括
#包括
#包括“Python.h”
结构RTMaps_GILLock
{
RTMaps_GILLock()
{

std::cout我遇到了您的问题,请确保不要从主线程调用PyGILState_sure(),主线程是初始化python的线程,因为它需要完全不同的调用。 我已经设置了一个线程映射器,每次调用acquirePython()都会检查调用它的线程,如果它是主线程,它会使用:

PyEval_SaveThread()

否则它将存储GIL。这些是我的类的相关部分:

void MManager::acquirePython(void) {
    MThread thisThread = MFramework::MProcesses::GetCurrentThread();
    if (thisThread != mainThread) {
        Lock();
        std::map<MThread,void*>::iterator i = threadStates.find(thisThread);
        if (i == threadStates.end()) {
            Unlock();
            PyGILState_STATE gstate = PyGILState_Ensure();
            _PyGILState_STATE_* encState = new _PyGILState_STATE_;
            encState->state = gstate;
            encState->refCount = 1;
            Lock();
            threadStates[thisThread] = encState;
            Unlock();
        } else {
            _PyGILState_STATE_* encState = (_PyGILState_STATE_*)i->second;
            encState->refCount = encState->refCount + 1;
            Unlock();
        }

    } else {
        if (mainThreadState) PyEval_RestoreThread((PyThreadState*)mainThreadState);
    }

}

void MManager::releasePython(void) {
    MThread thisThread = MFramework::MProcesses::GetCurrentThread();
    if (thisThread != mainThread) {
        Lock();
        std::map<MThread,void*>::iterator i = threadStates.find(thisThread);
        if (i != threadStates.end()) {
            _PyGILState_STATE_* encState = (_PyGILState_STATE_*)i->second;
            if (encState->refCount <= 1) {
                threadStates.erase(i);
                Unlock();

                PyGILState_Release(encState->state);
                delete encState;
            } else {
                encState->refCount = encState->refCount - 1;
                Unlock();
            }
        } else {
            Unlock();
        }

    } else {
        mainThreadState = PyEval_SaveThread();
    }
}
void MManager::acquirePython(void){
MThread thisThread=MFramework::MProcesses::GetCurrentThread();
if(thisThread!=主线程){
锁();
std::map::iterator i=threadStates.find(thisThread);
如果(i==threadStates.end()){
解锁();
PyGILState_STATE gstate=PyGILState_sure();
_PyGILState\u STATE\u*encState=new\u PyGILState\u STATE;
encState->state=gstate;
encState->refCount=1;
锁();
ThreadState[ThistThread]=encState;
解锁();
}否则{
_PyGILState\u STATE\u*encState=(\u PyGILState\u STATE)i->second;
encState->refCount=encState->refCount+1;
解锁();
}
}否则{
if(mainThreadState)PyEval_RestoreThread((PyThreadState*)mainThreadState);
}
}
void MManager::releasePython(void){
MThread thisThread=MFramework::MProcesses::GetCurrentThread();
if(thisThread!=主线程){
锁();
std::map::iterator i=threadStates.find(thisThread);
如果(i!=threadStates.end()){
_PyGILState\u STATE\u*encState=(\u PyGILState\u STATE)i->second;
如果(encState->refCount状态);
删除国家;
}否则{
encState->refCount=encState->refCount-1;
解锁();
}
}否则{
解锁();
}
}否则{
mainThreadState=PyEval_SaveThread();
}
}

这是唯一涉及的线程吗?一般来说,当Python调用C时,GIL已经被获取。有没有可能在没有明确获取GIL的情况下,在C内部有另一个阻塞的线程?@Kevin有。顺便说一句,Python没有机会调用C。在我死锁之前,我只有时间在线程A中初始化Python,而当线程B来做一些工作,但它被卡在了第一个锁中。实际上,线程A在我的应用程序结束之前不会再接触Python了,还有什么要做的吗?我已经阅读了1000次文档,我所做的应该可以工作了……我已经讨厌GIL了。@Kevin我重写了我的帖子,展示了一个每个人都可以编译和测试的完整示例。This示例失败。我已将我的帖子完全更新为一个更简单的示例,您可以编译。GIL锁是在与主线程不同的线程上完成的。因此,我不应该陷入您描述的问题中。您需要在主函数中,从调用PyInitialize()的主线程调用PyEval_InitThreads()@然后,OP需要从主线程释放GIL,因为InitThreads获得了它。你是对的,我需要调用
PyEval\u SaveThread
从主线程释放GIL。
void MManager::acquirePython(void) {
    MThread thisThread = MFramework::MProcesses::GetCurrentThread();
    if (thisThread != mainThread) {
        Lock();
        std::map<MThread,void*>::iterator i = threadStates.find(thisThread);
        if (i == threadStates.end()) {
            Unlock();
            PyGILState_STATE gstate = PyGILState_Ensure();
            _PyGILState_STATE_* encState = new _PyGILState_STATE_;
            encState->state = gstate;
            encState->refCount = 1;
            Lock();
            threadStates[thisThread] = encState;
            Unlock();
        } else {
            _PyGILState_STATE_* encState = (_PyGILState_STATE_*)i->second;
            encState->refCount = encState->refCount + 1;
            Unlock();
        }

    } else {
        if (mainThreadState) PyEval_RestoreThread((PyThreadState*)mainThreadState);
    }

}

void MManager::releasePython(void) {
    MThread thisThread = MFramework::MProcesses::GetCurrentThread();
    if (thisThread != mainThread) {
        Lock();
        std::map<MThread,void*>::iterator i = threadStates.find(thisThread);
        if (i != threadStates.end()) {
            _PyGILState_STATE_* encState = (_PyGILState_STATE_*)i->second;
            if (encState->refCount <= 1) {
                threadStates.erase(i);
                Unlock();

                PyGILState_Release(encState->state);
                delete encState;
            } else {
                encState->refCount = encState->refCount - 1;
                Unlock();
            }
        } else {
            Unlock();
        }

    } else {
        mainThreadState = PyEval_SaveThread();
    }
}