1. 程式人生 > >Python 多執行緒 多程序 全域性直譯器鎖GIL join

Python 多執行緒 多程序 全域性直譯器鎖GIL join

Python 程式碼的執行由Python 虛擬機器(也叫直譯器主迴圈)來控制。Python 在設計之初就考慮到要在主迴圈中,同時只有一個執行緒在執行,就像單CPU 的系統中執行多個程序那樣,記憶體中可以存放多個程式,但任意時刻,只有一個程式在CPU 中執行。同樣地,雖然Python 直譯器中可以“執行”多個執行緒,但在任意時刻,只有一個執行緒在直譯器中執行。 上面是官方的說法,通俗一點講就是,python程式本身只佔用cpu的一個執行緒,於是python所謂的多執行緒程式設計就類似於單CPU情況下的多程序程式設計。 下面說一下CPU情況下的多程序執行: 多個程序序列通過排程器協調後順序輸入到cpu進行計算,你可以把多工看成幾條溪流,然後排程器是最後的融匯口,進行融匯後流入CPU計算,但是不同的是,單位時間流入CPU的量是一定的,所以把任務分為多程序後進行CPU計算的量和分割前CPU計算量基本一樣。 所以對於計算密集型的任務,分為多程序並不會減少計算時間,反而增加了,因為增加了排程時間。 對於IO密集型的任務,多程序是可以的,因為IO密集型對CPU佔用相對較少,CPU不會處於滿負荷狀態,減少了IO的等待時間。 為什麼IO可以省時間,計算型密集不可以呢? 我是這麼認為的,計算密集型的任務,不管是否分割為多程序,CPU在任務執行期間一直是滿負荷的(不管是直接執行這個完整的任務,還是順序或者排程方式執行多個程序),並不存在空閒資源。 而IO密集型的任務,不管是CPU還是IO,都基本不會使資源滿負荷,那麼,我們可以把程序分割,讓分割出的部分利用好這些資源,所以節省了時間。 下面這個解釋也不錯: 單cpu多道程序系統有如下特徵: ①從巨集觀上看,幾道程式“同時進行”。即他們先後開始了給的執行且均未結束。 ②從微觀上看,幾道程式“交替執行”。對於單cpu程序而言,他們只是輪流佔用cpu。 CPU在各程序之間來回切換,,這種快速切換成為多道程式設計。每個程序有自己的控制流程,並且每個都獨立地執行。實際上只有一個物理程式計數器,所以在每個程式執行時,他的邏輯計數器被裝入設計的程式計數器中。隨著時間的推移,當程式結束是,物理程式計數器被儲存在記憶體中該程序的邏輯程式計數器中。所有程序都有所進展,但一個給定的瞬間僅有一個程序真正在執行。 然後我們再來看Python的多執行緒: 首先確定的是,python在執行過程中每個時刻,其實都只有一個執行緒在工作。而你所開啟的多執行緒,被編譯成可執行程式碼放到記憶體中,被任務排程器排程放到這一條“執行緒流”中,而執行這個排程的,就是全域性直譯器鎖(GIL)。 介紹幾個python多執行緒相關的關鍵字:thread和threading、守護執行緒、join Python裡面有兩個執行緒操作模組thread和threading,用thread建立多執行緒時,當主執行緒結束時,所有的執行緒都會被強制結束掉,沒有警告也不會有正常的清除工作。threading 模組能確保重要的子執行緒退出後進程才退出。 守護執行緒:如果你的主執行緒要退出的時候,不用等待那些子執行緒完成,那就設定這些執行緒的daemon 屬性。即,線上程開始(呼叫thread.start())之前,呼叫setDaemon()函式設定執行緒的daemon 標誌(thread.setDaemon(True))就表示這個執行緒“不重要”。 join:你的python主程式相當於預設存在的一個執行緒,而當你通過threading新建執行緒時,這個執行緒會隨著start方法開始跟主程式平行計算,如果不設定join,那麼從這個執行緒start開始,他就與python主程式並行了,join的作用是,當你在python主程式中開啟了多個執行緒並設為join時,這些執行緒會被附加到主程式上。
#coding=utf-8
import threading import time threads=[] def func(x): print 'hello',x time.sleep(x) print 'I have sleep %d seconds'%x cur=time.clock() for i in range(3): threads.append(threading.Thread(target=func,args=(i+2,))) for thread in threads: thread.start() thread.join() print 'finish!'
print time.clock()-cur
輸出: hello 2
I have sleep 2 seconds
hello 3
I have sleep 3 seconds
hello 4
I have sleep 4 seconds
finish!
9.0039654844
#coding=utf-8
import threading
import time
threads=[]
def func(x):
    print 'hello',x
    time.sleep(x)
    print 'I have sleep %d seconds'%x

for i in range(3
): threads.append(threading.Thread(target=func,args=(i+2,))) for thread in threads: thread.start() #thread.join() print 'finish!'
輸出: hello 2
hello 3
hellofinish! 
4
I have sleep 2 seconds
I have sleep 3 seconds
I have sleep 4 seconds
解釋一下: hellofinish! 
4
這裡並行執行了print 'hello',4        ;         print 'finish!' 前一條相當於print 'hello',  ,注意語句末尾的逗號和 print ’4‘ 在排程時後面一條差到了中間,就打印出了上述結果。 python多程序: Python提供了multiprocessing處理多程序任務,有興趣可以看看。