细心的人可能已经发现了,在《Cython进阶--用Cython封装Callback函数》中,每次获取GIL都要调用一下PyGILState_Ensure,释放时又要调用PyGILState_Release,
为了防止已经获取GIL的线程在执行I/O操作而导致其它运行Python代码的线程暂时获取不到GIL而被迫暂停,更有甚者如果已经获取GIL的线程调用的某一个C函数在等待一个mutex,而另一个负责释放这个锁的线程却在等待获取GIL,根本无法释放这个mutex,那就造成了死锁!为了避免这种情况的发生,就要在调用C函数之前调用PyEval_SaveThread 暂时释放GIL,函数调用完时调用PyEval_RestoreThread重新获取。
这样是不是太麻烦了,实际上,cython的设计者们早就为我们考虑到了这点,方法就是用with gil和with nogil语句块。
这也再一次印证了一句话:只有想不到的,没有做不到的
你在遇到一个问题时,99.99999999%的概率别人已经解决过了,如果恰巧碰上了0.0000000001%的概率,那么你应该感到幸运。
先来看下面的例子:
cdef extern from"pthread.h":
ctypedef void * pthread_t
ctypedef struct pthread_attr_t:
pass
int pthread_create (pthread_t *__newthread,\
pthread_attr_t *__attr, \
void*(*__start_routine)(void *)except*, \
void *__arg)
int pthread_join (pthread_t __th,void**__thread_return) nogil
cdef extern from"Python.h":
ctypedef enum PyGILState_STATE:
pass
ctypedef enum PyThreadState:
pass
void PyEval_InitThreads()
void Py_INCREF(object obj)
void Py_DECREF(object obj)
def Callback(obj):
if hasattr(obj,'run'):
obj.run()
cdef void * start (void *param)except*with gil:
cdef object obj =