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;
}