Python C API关于GIL的细节

本文介绍如何在嵌入式Python环境中手动管理全局解释器锁(GIL),包括如何初始化GIL、在多线程环境下如何获取和释放GIL,以及提供了一个具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  GIL的创建是手动的。意味着单线程的Python程序运行起来是没有任何问题的,也没有关于锁的损失。thread库等Python标准库会在内部调用 PyEval_InitThreads()来创建GIL。而在嵌入式的Python(Embeded Python),则需要手动地调用此函数。

   在嵌入式Python中,我们还需要在主线程使用线程时,把线程开始运行的代码放在Py_BEGIN_ALLOW_THREADS和 Py_END_ALLOW_THREADS之间,而且需要保证在Py_END_ALLOW_THREADS之后不再在子线程调用关于Python的脚本代 码,但是有时还是可以调用Python 的C API。同时在所有子线程调用Python脚本代码的时候,需用PyGILState_Ensure获得GIL。在结束调用时候调用 PyGILState_Release。

 

P.S 代码

DWORD MyThreadRoutine(LPVOID);

struct MyValue{
    PyObject * pValue;
    PyObject * pFunc;
};
typedef struct MyValue MyValue_t;
int _tmain(int argc, _TCHAR* argv[])
{
    PyObject *pName, *pModule, *pFunc,*pFunc1;
    PyObject *pArgs, *pValue;
    //PyGILState_STATE gstate;
    int ret=0;


    Py_Initialize();
    PyEval_InitThreads();
    fprintf(stderr,"aquiring gil from main lock/n");
    //gstate = PyGILState_Ensure();

    pName = PyString_FromString("MyModule");
   
    pModule = PyImport_Import(pName);
    Py_DECREF(pName);
    if (pModule == NULL){
        fprintf(stderr,"failed to import module/n");
        PyErr_Print();
        return 1;
    }
    pFunc = PyObject_GetAttrString(pModule, "fun1");
    if (!pFunc || !PyCallable_Check(pFunc)){
        fprintf (stderr,"failed to get function!");
        ret=1;
        goto failed2;
    }
    pFunc1 = PyObject_GetAttrString(pModule, "fun2");
    if (!pFunc1 || !PyCallable_Check(pFunc1)){
        fprintf (stderr,"failed to get function 2!");
        ret=1;
        goto failed3;
    }
    pArgs=Py_BuildValue("(s)","linzuojian");
    if(pArgs==NULL){
        ret=1;
        goto failed4;
    }
    pValue = PyObject_CallObject(pFunc, pArgs);
    if (PyErr_Occurred()){
        fprintf(stderr,"Failed to call object!/n");
        PyErr_Print();
        ret=1;
        goto failed;
    }
    Py_BEGIN_ALLOW_THREADS
    fprintf(stderr,"Main thread releasing lock/n");
    HANDLE hThread,hThread_2nd;
    DWORD dwThreadID;
    struct MyValue myvalue;
    myvalue.pFunc=pFunc1;
    myvalue.pValue=pValue;
    hThread=CreateThread(NULL,0,MyThreadRoutine,&myvalue,0,&dwThreadID);
    if(hThread==NULL){
        fprintf(stderr,"Failed to create thread/n");
        ret=1;
        goto failed;
    }
    hThread_2nd=CreateThread(NULL,0,MyThreadRoutine,&myvalue,0,&dwThreadID);
    if(hThread_2nd==NULL){
        fprintf(stderr,"Failed to create thread/n");
        ret=1;
        goto failed;
    }
    WaitForSingleObject(hThread,INFINITE);
    WaitForSingleObject(hThread_2nd,INFINITE);
    Sleep(1000);
    fprintf(stderr,"Exit.../n");
    Py_END_ALLOW_THREADS
failed:
   
    Py_DECREF(pArgs);
   
    Py_XDECREF(pValue);
failed4:
    Py_XDECREF(pFunc1);
failed3:
    Py_DECREF(pFunc);
failed2:
    Py_DECREF(pModule);
    return ret;
}



DWORD MyThreadRoutine(LPVOID pObject){
    PyObject * pargs;
    PyGILState_STATE state;
    MyValue_t *pValue=(MyValue_t*)pObject;

    fprintf(stderr,"Acquiring lock.../n");
    state=PyGILState_Ensure();
    Py_INCREF(pValue->pFunc);
    Py_INCREF(pValue->pValue);

    pargs=Py_BuildValue("(O)",pValue->pValue);
    if(pargs==NULL){
        fprintf(stderr,"Build args for fun1 failed/n");
        return 1;
    }
    PyObject_CallObject(pValue->pFunc, pargs);
    fprintf(stderr,"Killing args here/n");
    Py_DECREF(pargs);
    Py_XDECREF(pValue->pValue);
    Py_XDECREF(pValue->pFunc);
    PyGILState_Release(state);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值