2014-03-25 14 views
2

我有以下Python代碼:當主線程運行一個無限循環時,爲什麼在一個不同的線程中導入一個模塊需要很長時間?

import threading 
from datetime import datetime 
import time 

def f(): 
    print('---- {:%H:%M:%S}'.format(datetime.now())) 
    import http.server 
    print('---- {:%H:%M:%S}'.format(datetime.now())) 

threading.Thread(target=f).start() 

while True: 
    pass 

當我執行它,我看到了大量時間消耗到import http.server。正如你從下面的輸出中可以看到的那樣,導入需要23秒。

C:\>python foo.py 
---- 10:12:03 
---- 10:12:26 

但是,如果我把一個小睡在無限循環while,進口發生得更快。

import threading 
from datetime import datetime 
import time 

def f(): 
    print('---- {:%H:%M:%S}'.format(datetime.now())) 
    import http.server 
    print('---- {:%H:%M:%S}'.format(datetime.now())) 

threading.Thread(target=f).start() 

while True: 
    time.sleep(1) 

輸出:

C:\>python foo.py 
---- 10:15:58 
---- 10:15:58 

我知道join()方法的用法,但我想確切地知道爲什麼它長時間這麼import http.server當無限while循環沒有處於睡眠聲明它。

+0

假設你幾乎沒有其他任何東西在運行,原因在於'while True'循環將經常發生,速度如此之快,以至於如果你這樣看,每個線程中的每個調用都會被賦予「拉鍊「的原則,每個線程在下一個線程獲得他/她的之前獲得一個CPU週期。因此,如果您要導入一個包含大量代碼的「大」模塊,那麼在每行之間需要一段時間,而「True」則需要循環並在處理器中佔用一個週期。 (粗略地說) – Torxed

+0

@Toxxed它只會在運行CPython解釋器的處理器核心上佔用99.9%的CPU週期。其他內核不受影響。 – ElmoVanKielmo

+0

很明顯是的,因爲Python不是開發出來的,可以在多個核心上運行。這也是我認爲不需要解釋的東西,所以我很久以前就刪除了我的描述中的那一部分:) – Torxed

回答

3

CPython使用Global Interpreter Lock來保護解釋器上下文。這可以防止線程在同一時間運行。實際上它們都運行在單處理器內核上。在CPython中,當他們執行類似閒置的操作時,您可以從線程中受益,即等待I.O.或者在套接字上監聽。
您爲主線程做了大量工作。儘管pass沒有任何意義,但它會消耗CPU週期,而且解釋程序認爲向該線程提供CPU時間非常重要。
With sleep你說don't waste anything for this thread until time expires

0

我不是這方面的專家,但據我所知,多個線程一個接一個地在同一核心上運行,所以這是一個CPU時間共享的問題。然後,將睡眠添加到無限循環將爲您的導入線程提供更多資源。 要並行運行使用多處理。那麼你的代碼將使用多個核心。 你可以看看這個簡單的example

+0

你應該說它是CPython實現的特定對象。 – ElmoVanKielmo

相關問題