淺析Python多線程問題
Python多線程環境的建立,說得直白一點,主要就是創建GIL。我們已經知道GIL對于Python的多線程機制的重要意義,然而這個GIL到底是如何實現的呢,哎這還是個非常困擾的問題。
- 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(interpreter_lock),沒想到吧,萬萬沒想到,它居然指示一個簡單的void*。但是轉念一想,在C中void*幾乎可以是任何東西,這家伙,可是個***容器啊。
可以看到,無論創建多少個線程,Python建立多線程環境的動作只會執行一次。在PyEval_InitThreads的開始,Python會檢查GIL是否已經被創建。如果是,則不再進行任何動作,否則,就會創建這個GIL。創建GIL的工作由PyThread_allocate_lock完成,我們來看一看這個GIL到底是何方神圣。
在這里,我們終于看到了Python多線程機制的平臺相關性,在Python25\Python目錄下,有一大批thread這樣的文件。在這些文件中,包裝了不同操作系統的原生線程,并通過統一的接口暴露給Python,比如這里的PyThread_allocate_lock就是這樣一個接口。#t#
我們這里的thread_nt.h中包裝的是Win32平臺的原生thread,在本章中后面的代碼剖析中,還會有大量與平臺相關的代碼,我們都以Win32平臺為例。在PyThread_allocate_lock中,與PyEval_InitThreads非常類似的,它會檢查一個initialized的變量,如果說GIL指示著Python多線程環境是否已經建立。
那么這個initialized變量就指示著為了使用底層平臺所提供的原生thread,必須的初始化動作是否完成。這些必須的初始化動作通常都是底層操作系統所提供的API,不同的操作系統可能需要不同的初始化動作。
在PyThread_allocate_lock中,出現了一個關鍵的結構體PNRMUTEX,我們發現,這個結構體是函數的返回值,實際上也就是PyEval_InitThread中需要創建的那個interperter_lock(GIL)。原來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 */
- }
在NRMUTEX中,所有的數據成員的類型都是Win32平臺下的類型風格了,owned和thread_id都很普通,而其中的HANDLE hevent卻值得注意,我們來看看AllocNon- RecursiveMutex究竟為這個hevent準備了什么。