sho*_*osh 17 c python multithreading python-embedding gil
我在一个多线程的C应用程序中嵌入python解释器,我有点困惑的是我应该使用什么API来确保线程安全.
从我收集的内容来看,嵌入python时,在调用任何其他Python C API调用之前,由嵌入器来处理GIL锁.这是通过以下功能完成的:
gstate = PyGILState_Ensure();
// do some python api calls, run python scripts
PyGILState_Release(gstate);
Run Code Online (Sandbox Code Playgroud)
但仅凭这一点似乎还不够.我仍然有随机崩溃,因为它似乎不提供Python API的互斥.
在阅读了更多文档后,我还补充说:
PyEval_InitThreads();
Run Code Online (Sandbox Code Playgroud)
在电话会议结束后,Py_IsInitialized()这就是令人困惑的部分.文档声明这个函数:
初始化并获取全局解释器锁
这表明当这个函数返回时,GIL应该被锁定并且应该以某种方式解锁.但实际上这似乎并不是必需的.有了这条线,我的多线程工作完美,并且PyGILState_Ensure/Release功能保持互斥.
当我尝试PyEval_ReleaseLock()在PyEval_ReleaseLock()应用程序死锁后很快在后续调用中添加PyImport_ExecCodeModule().
那我在这里错过了什么?
我有完全相同的问题,现在通过使用PyEval_SaveThread()后立即解决PyEval_InitThreads(),如上所述.但是,我的实际问题是我PyEval_InitThreads()之后PyInitialise()使用然后PyGILState_Ensure()在从不同的后续本机线程调用时导致阻塞.总之,这就是我现在所做的:
有全局变量:
static int gil_init = 0;
Run Code Online (Sandbox Code Playgroud)从主线程加载本机C扩展并启动Python解释器:
Py_Initialize()
Run Code Online (Sandbox Code Playgroud)从多个其他线程,我的应用程序同时对Python/C API进行了大量调用:
if (!gil_init) {
gil_init = 1;
PyEval_InitThreads();
PyEval_SaveThread();
}
state = PyGILState_Ensure();
// Call Python/C API functions...
PyGILState_Release(state);
Run Code Online (Sandbox Code Playgroud)从主线程停止Python解释器
Py_Finalize()
Run Code Online (Sandbox Code Playgroud)我尝试过的所有其他解决方案都会导致随机的Python sigfaults或死锁/阻塞PyGILState_Ensure().
Python文档确实应该更清楚,至少为嵌入和扩展用例提供了一个示例.
最终我想通了。
后
PyEval_InitThreads();
Run Code Online (Sandbox Code Playgroud)
你需要打电话
PyEval_SaveThread();
Run Code Online (Sandbox Code Playgroud)
同时适当释放主线程的GIL。