如何進行建立Python主線程?
在Python里如果你建立一個程序,就是一個進程,其中包含一個線程,這個就是主線程,而是為了提高資源使用效率來提高系統的效率,希望大家能夠再次學到自己想要的信息。
從這里可以看到,當一個線程開始等待GIL時,其owned就會被增加1。顯然我們可以猜測,當一個線程最終釋放GIL時,一定會將GIL的owned減1,這樣當所有需要GIL的線程都最終釋放了GIL之后,owned會再次變為-1,意味著GIL再次變為可用。
為了清晰地展示這一點,我們現在就來看看PyThread_aquire_lock的逆運算,PyThread_release_lock每一個將從運行轉態轉為等待狀態的線程都會在被掛起之前調用它以釋放對GIL的占有。
- [thread_nt.h]
- PNRMUTEX AllocNonRecursiveMutex(void)
- {
- PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ;
- if(mutex && !InitializeNonRecursiveMutex(mutex)) {
- free(mutex);
- Mutex = NULL;
- }
- return mutex ;
- }
- BOOL InitializeNonRecursiveMutex(PNRMUTEX mutex)
- {
- ……
- mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
- mutex->thread_id = 0 ;
- mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
- return mutex->hevent != NULL ; /* TRUE if the mutex is created */
- }
最終,一個線程在釋放GIL時,會通過SetEvent通知所有在等待GIL的hevent這個Event內核對象的線程,結合前面的分析,如果這時候有線程在等待GIL的hevent,那么將被操作系統喚醒。
這就是我們在前面介紹的Python將線程調度的第二個難題委托給操作系統來實現的機制。到了這時,調用PyEval_InitThread的線程(也就是Python主線程)已經成功獲得了GIL。***會調用PyThread_get_thread_ident()。
通過Win32的API:GetCurrent- ThreadId,獲得當前Python主線程的id,并將其賦給main_thread,main_thread是一個靜態全局變量,專職存儲Python主線程的線程id,用以判斷一個線程是否是Python主線程。
在完成了多線程環境的初始化之后,Python會開始創建底層平臺的原生thread,以thread1.py為例,這個原生thread將執行threadProc所定義的操作。從現在開始,為了描述的清晰性,我們將Python主線程,也就是調用thread_PyThread_start_new_thread創建新的線程的線程稱為主線程,而將與threadProc對應的原生thread稱之為子線程?,F在我們來看看一個子線程是如何被創建的。
- static PyObject* thread_PyThread_start_new_thread(PyObject *self, PyObject
- *fargs)
- {
- PyObject *func, *args, *keyw = NULL;
- struct bootstate *boot;
- long ident;
- PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, &func, &args, &keyw);
- //[1]:創建bootstate結構
- boot = PyMem_NEW(struct bootstate, 1);
- boot->interp = PyThreadState_GET()->interp;
- boot->funcfunc = func;
- boot->argsargs = args;
- boot->keywkeyw = keyw;
- //[2]:初始化多線程環境
- PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
- //[3]:創建線程
- ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
- return PyInt_FromLong(ident);
- [thread.c]
- /* Support for runtime thread stack size tuning.
- A value of 0 means using the platform's default stack size
- or the size specified by the THREAD_STACK_SIZE macro. */
- static size_t _pythread_stacksize = 0;
- [thread_nt.h]
- long PyThread_start_new_thread(void (*func)(void *), void *arg)
- {
Python主線程通過調用PyThread_start_new_thread完成創建子線程的工作。為了清晰地理解PyThread_start_new_thread的工作,我們需要特別注意該函數的參數。從thread_ PyThread_start_new_thread中可以看到,這里的func實際上是函數t_bootstrap,而arg則是在thread_PyThread_start_new_thread中創建的bootstate結構體boot。在boot中,保存著Python程序(thread1.py)中所定義的線程的信息。
【編輯推薦】


















