如何進行Python主線程設置
下面給大家一個寶貴的建議,對于那些從來沒有學習過編程或者并非計算機專業的編程學習者而言,Python主線程是最好的選擇之一,并建議那些初學的程序員先從Python開始學習編程。
如果waitflag為0,Python會檢查當前GIL是否可用,GIL中的owned是指示GIL是否可用的變量,在前面的InitializeNonRecursiveMutex中我們看到這個值被初始化為-1,Python會檢查這個值是否為-1,如果是,則意味著GIL可用。
必須將其置為0,當owned為0后,表示該GIL已經被一個線程占用,不再可用。對于我們這里分析的調用PyEval_InitThread的主線程而言,由于在初始化GIL之后就調用PyThread_ acquire_lock申請GIL。
到這時,并沒有第二個線程被創建,所以主線程會輕而易舉地獲得GIL的使用權。注意這里的檢查和更新owned的操作是通過一個Win32的系統API——Interlocked- CompareExchange——來完成的。這個API是一個原子操作,其函數原形和功能如下。
與InterlockedCompareExchange相同的,InterlockedIncrement也是一個原子操作,其功能是將mutex->owned的值增加1。從這里可以看到,當一個線程開始等待GIL時,其owned就會被增加1。
顯然我們可以猜測,當一個線程最終釋放GIL時,一定會將GIL的owned減1,這樣當所有需要GIL的線程都最終釋放了GIL之后,owned會再次變為-1,意味著GIL再次變為可用。
為了清晰地展示這一點,我們現在就來看看PyThread_aquire_lock的逆運算,PyThread_release_lock每一個將從運行轉態轉為等待狀態的線程都會在被掛起之前調用它以釋放對GIL的占有。
- void PyThread_release_lock(PyThread_type_lock aLock)
- {
- LeaveNonRecursiveMutex((PNRMUTEX) aLock);
- }
- BOOL LeaveNonRecursiveMutex(PNRMUTEX mutex)
- {
- /* We don't own the mutex */
- mutex->thread_id = 0 ;
- return
- InterlockedDecrement(&mutex->owned) < 0 ||
- SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on
- them up */
- }
最終,一個線程在釋放GIL時,會通過SetEvent通知所有在等待GIL的hevent這個Event內核對象的線程,結合前面的分析。如果這時候有線程在等待GIL的hevent,那么將被操作系統喚醒。這就是我們在前面介紹的Python主線程將線程調度的第二個難題委托給操作系統來實現的機制。
到了這時,調用PyEval_InitThread的線程(也就是Python主線程)已經成功獲得了GIL,最后會調用PyThread_get_thread_ident(),通過Win32的API:GetCurrent- ThreadId,獲得當前Python主線程的id。
【編輯推薦】