我正在编写一个C程序,它使用用python编写的网络库.我用python C api嵌入了python lib.该库发送所有请求异步,并在请求完成时通过信号通知我.
这在理论上意味着.
实际上我有两个与线程相关的问题:
我做错了什么?有什么东西要做多线程工作吗?
我有类似的情况.
初步工作流程
从一开始,事件线程就意外地工作了.我想这是因为GIL来自我遇到的情况所以我试图从GIL解决这个问题.这是我的解决方案.
分析
首先,从PyEval_InitThreads中的注释,
仅存在主线程时,不需要GIL操作....因此,最初不会创建锁....
因此,如果需要多线程,则PyEval_InitThreads()
必须在主线程中调用.我PyEval_InitThreads()
之前打过电话Py_Initialize()
.现在GIL已初始化,主线程获取GIL.
其次,每次从C++层调用Python函数之前,PyGILState_Ensure()
都会调用它来获取GIL.另外,在调用Python函数之后,PyGILState_Release(state)
调用它回到之前的GIL状态.结果,在步骤2之前,PyGILState_Ensure()
调用,并在步骤4之后,PyGILState_Release(state)
调用.
但有一个问题.从PyGILState_Ensure和PyGILState_Release,这两个函数是保存当前GIL状态以获取GIL并恢复以前的GIL状态以释放GIL.但是,PyEval_InitThreads()
在主线程调用之后,主线程肯定拥有GIL.主线程中的GIL状态如下:
/* main thread owns GIL by PyEval_InitThreads */
state = PyGILState_Ensure();
/* main thread owns GIL by PyGILState_Ensure */
...
/* invoke Python function */
...
PyGILState_Release(state);
/* main thread owns GIL due to go back to previous state */
Run Code Online (Sandbox Code Playgroud)
从上面的代码示例中,主线程总是拥有GIL,因此事件线程永远不会运行.要克服这种情况,让主线程在调用之前不要获取GIL PyGILState_Ensure()
.因此,在调用之后PyGILState_Release(state)
,主线程可以释放GIL以让事件线程运行.因此,当GIL初始化时,应立即在主线程中释放GIL.
这PyEval_SaveThread()
是用的.从PyEval_SaveThread,
释放全局解释器锁(如果已创建并启用了线程支持)并将线程状态重置为NULL,...
通过这样做,嵌入Python与多线程工作.
修改后的工作流程
PyEval_InitThreads();
启用多线程save = PyEval_SaveThread();
在主线程中释放GILstate = PyGILState_Ensure();
在主线程中获取GILPyGILState_Release(state);
在主线程中释放GIL 归档时间: |
|
查看次数: |
762 次 |
最近记录: |