如何证明多线程下用c调用python的时候,python会定期切换出当前的线程,释放全局锁,然后换给其他线程执行。
基本思路:在调用的python函数中,让这个函数睡眠2秒钟,此时这个线程拿到了GIL,按理说应该等这个线程函数睡足了2秒钟才切换到下一个线程。
import time
def my_pFun(a, l):
print "a = : " + str(a)
print str(l) + " : start time" + str(time.time())
time.sleep(2) #三个线程都调用这个函数,睡眠2秒钟
print str(l) + " : end time" + str(time.time())
#include <Python.h>
#include <pthread.h>
#include <iostream>
using namespace std;
class PyThreadStateLock
{
public:
PyThreadStateLock()
{
state = PyGILState_Ensure();
}
~PyThreadStateLock()
{
PyGILState_Release(state);
}
private:
PyGILState_STATE state;
};
PyObject* pFunc = NULL;
void pFunc_init()
{
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
//PyRun_SimpleString("import time");
PyObject* pyModule = PyImport_Import(PyString_FromString("mypy"));
if(pyModule == NULL)
{
printf("load mypy failed\n");
exit(0);
}
PyObject* pDict = PyModule_GetDict(pyModule);
pFunc = PyDict_GetItemString(pDict, "my_pFun");
}
void * threadFunc(void* arg)
{
//PyEval_ReleaseLock();
long tid = pthread_self();
pthread_detach(pthread_self());
PyObject* pkwargs = NULL;
PyThreadStateLock PyThreadLock;
int a = *(int*)arg;
delete (int*)arg;
cout << "********in thread:" << pthread_self() << " **** a:" << a << endl;
PyObject* pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("l", tid));
PyObject_Call(pFunc, pArgs, pkwargs);
cout << "c sleep in : " << pthread_self() << endl;
sleep(3);
//exit(0);
//pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
Py_Initialize();
PyEval_InitThreads();
pFunc_init();
pthread_t tid[3];
PyEval_ReleaseThread(PyThreadState_Get());
for(int i = 0; i < 3; i++)
{
int* j = new int(i);
pthread_create(&tid[i], NULL, threadFunc, j);
}
for(int i = 0; i < 3; i++)
{
pthread_join(tid[i], NULL);
}
PyGILState_Ensure();
Py_Finalize();
return 0;
}
运行结果可以看到,这三个线程函数中的sleep几乎是同时开始的,然后几乎是同时结束的,可以看出,在操作系统的底层,会对占用GIL的线程进行定期的切换,当第一个线程开始sleep之后,马上换到第二个线程去执行,当它睡眠之后,又换到第三个线程执行,切换的时候肯定保存了线程执行的上下文,以便再次被调度继续执行。所以这三个python程序的sleep几乎是同时进行,同时结束的,所以可以说明,python的多线程处理阻塞性(比如IO)任务还是可以的。