我嵌入在多线程C应用程序的Python解释器,我为我应该用什么API来保证线程安全有点困惑。
从我收集的,嵌入蟒蛇时,它是到嵌入照顾GIL锁调用任何其他Python C API调用之前。 这是通过这些功能来完成:
gstate = PyGILState_Ensure();
// do some python api calls, run python scripts
PyGILState_Release(gstate);
但仅此似乎并不足够。 我还有随机崩溃,因为似乎提供了Python API的互斥它不会。
阅读一些文档我还添加了后:
PyEval_InitThreads();
在调用之后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;
从主线程加载本地C扩展,并启动Python解释器:
Py_Initialize()
从多个其他线程我的应用程序同时使得很多电话到Python / C API的:
if (!gil_init) { gil_init = 1; PyEval_InitThreads(); PyEval_SaveThread(); } state = PyGILState_Ensure(); // Call Python/C API functions... PyGILState_Release(state);
从主线程停止Python解释器
Py_Finalize()
我已经尝试了所有其他解决方案,无论是造成随机的Python sigfaults或死锁/使用阻塞PyGILState_Ensure()
Python文档确实应该对这个更加清晰,至少两个嵌入和扩展使用案例提供了一个例子。
具有多线程应用程序的ç试图从多个线程进行通信,以单一的CPython实例的多个线程的Python看起来危险的我。
只要只有一种C线与Python通信,你不应该担心锁定即使Python应用程序是多线程。 如果需要多个线程蟒可以设置应用了这种方式,并有多个C线程通过与一个C线程养殖场出来到多线程的Python队列通信。
这可能为你工作的替代方法是有多个实例CPython的一个关于C线程需要它(的Python程序之间的通信过程中应该可以通过C程序)。
另一种选择可能的Stackless的Python解释器。 这摒弃了GIL,但我不知道您遇到了其他问题,它绑定到多个线程。 无堆栈是一个简易替换为我(单线程)C应用。