一、概念
執行緒:執行緒就是乙個指令集合,是作業系統能夠進行運算排程的最小單位,他被包含在程序之中,是程序中的實際運作單位,執行緒之間資源可以共享
程序:程序就是對一些資源的整合,乙個程序可以有多個執行緒,程序之間資源不可以共享,程序之間是獨立
gil:全域性直譯器鎖,就是在python中同一時刻,只能有乙個執行緒被直譯器cpython執行
執行緒與程序的區別:
1.python中可以有多執行緒,也可以有多程序,在多程序中,子程序是完全複製的主程序的,所以多程序的資源消耗比多執行緒要大很多
2.執行緒資源、資料都是共享的,程序之間資源、資料都是獨立的
3.主線程可以影響子執行緒,但是主程序不會影響子程序
注:執行緒和程序一樣塊(執行緒在執行時,等於程序,同乙個體系)
二、python多執行緒執行過程:
python多執行緒過程:多個任務同時交給cpu進行處理,cpu會先執行乙個任務一小段時間,之後轉到另乙個任務在執行一小段時間(很短很短的時間),這個很短的時候看不出來差異,所以表面上看起來像是一起執行,實際其實就是乙個多個執行緒(併發)在競爭資源的過程,這種其實就叫多執行緒的併發執行,所以python中的多執行緒並不是並行執行,而是併發執行,也就是「交替執行」
交替切換執行緒有兩種方式:
1)規定的乙個很短的執行時間來切換執行緒
2)遇到i/o阻塞,如sleep(),他的效果就是型別i/o阻塞,當cpu執行某個執行緒,時間還沒到規定的那個很短時間,但是碰到了sleep語句,cpu就會切換到另乙個執行緒
python要真正的多執行緒並行執行是沒辦法的
而且通過這個圖發現,python由於在cpython直譯器上有乙個gil,在同一時刻,只能有乙個執行緒進入cpython直譯器執行,所以即使計算機存在多核,python的多執行緒也沒辦法像真正的並行執行一樣,使用多核來進行並行,這個是cpython直譯器的乙個歷史問題
如果要使用到多核,可以考慮用多程序的方法或者使用其他語言,其他語言如c就沒有gil這個問題
三、多執行緒處理任務:
1、任務型別:
1)io密集型任務函式:是指磁碟io、網路io佔主要的任務,計算量很小, 就是函式裡面有io阻塞,比如請求網頁、讀寫檔案等。阻塞時cpu處於空閒狀態,此時其他執行緒可使用cpu, python中可以利用sleep達到io密集型任務的目的
2)計算密集型任務函式:指cpu計算佔主要的任務,cpu一直處於滿負荷狀態。如複雜的加減乘除等
2.示例
下面我們看下使用多執行緒處理io密集型任務和計算密集型任務情況:
1)多執行緒下處理io密集型任務
普通序列:
def foo(n):print("foo %s" % n)
time.sleep(2)
print("end foo")
def bar(b):
print("bar %s" % b)
time.sleep(1)
print("end bar")
foo(2)
bar(1)
多執行緒處理io密集任務:
import threading2)多執行緒處理計算密集型任務import time
start=time.time()
def foo(n):
print("foo %s" % n)
time.sleep(2)
print("end foo")
def bar(b):
print("bar %s" % b)
time.sleep(1)
print("end bar")
t1=threading.thread(target=foo,args=(2,))
t2=threading.thread(target=bar,args=(1,))
t1.start() #執行子執行緒t1
t2.start() #執行子執行緒t2
print("this is main")
t1.join() #t1程序執行完成後才往下走,未執行完不往下走
t2.join() #t2程序執行完成後才往下走,未執行完不往下走
end=time.time()
print("spend time %s" %(end-start))
普通序列:
begin=time.time()def adds(n):
suma=0
for i in range(n):
suma+=i
print(suma)
adds(100000000)
adds(100000000)
endtime=time.time()執行緒併發執行:print(endtime-begin)
import threadingimport time
begin=time.time()從兩段指令碼可以看出,在python2.7裡面,處理io密集任務時,多執行緒耗時比普通序列要少,而處理計算密集型任務時,多執行緒併發執行花費的時間比普通的序列執行還要久,這主要的原因還是在adds這個函式,這個函式他沒有任何io阻塞,所以兩個執行緒的執行只能通過固定的一小段時間進行切換進行,實際和兩個adds序列是一樣的,同時切換執行緒還要消耗時間,所以執行緒併發執行實際耗費的時間比普通的序列執行還要久。def adds(n):
suma=0
for i in range(n):
suma+=i
print(suma)
t1=threading.thread(target=adds,args=(100000000,))
t2=threading.thread(target=adds,args=(100000000,))
t1.start()
t2.start()
t1.join()
t2.join()
endtime=time.time()
print(endtime-begin)
所以,在python裡面,處理io密集型任務時可以用多執行緒,如果處理的是計算密集型任務則使用多程序或者用其他語言的多執行緒(如c語言的多執行緒)
為什麼呢?
這是因為python有gil(全域性解釋鎖)的原因,導致同一時刻只能有乙個執行緒在使用cpu,所以即使計算機有多個cpu,在處理計算密集型任務時多執行緒並不能真的提高速度,反而會變慢,但是其他語言就沒有這個gil的問題,所以可以用多個cpu進行真的並行
四、乙個簡單的多執行緒處理io密集型任務示例:
import threading
import time
def music(name):
for i in range(2):
print("start listen music %s,time: %s" % (name,time.ctime()))
time.sleep(1)
print("end listen music,time:%s"%time.ctime())
def movie(name):
for i in range(2):
print("start watch movie %s,time: %s" % (name,time.ctime()))
time.sleep(5)
print("end watch movie,time:%s"%time.ctime())
五、主要引數
1、join():執行緒同步,即主線程執行完成後進入阻塞狀態,一直等待其他的子執行緒(誰呼叫的就等誰)執行結束之後,主線程在終止,在子執行緒執行完成之前,這個子執行緒的父執行緒一直被阻塞
2.setdaemon(true):守護執行緒,一般多執行緒執行時主線程執行完成後還會等子執行緒,之後程式才會結束,如果設定了執行緒守護,則表示哪個執行緒呼叫了setdaemon(true),這個程式除呼叫的執行緒外的其他執行緒執行結束後程式就結束,不會等待這個執行緒的執行結果
3.threading.current_thread():獲取到當前執行的執行緒資訊
4.threading.active_count():獲取當前仍啟用執行緒數量
執行緒和程序
標準的定義是 程序是執行緒的容器,乙個程序可於乙個或者多個執行緒,它是系統分配資源的基本單位 同乙個程序下,執行緒共享位址空降 已經開啟的檔案 訊號處理函式 報警訊號和其他,執行緒自己只保留程式計數器和棧。但是很遺憾的,這個只是教科書上的定義,實際情況是每個作業系統實現的作業系統特性不同,實現的方法...
程序和執行緒
乙個程序就是當前正在執行的乙個程式,包括程式的暫存器 程式計數器和變數的當前值。不同的程序擁有不同的位址空間。而執行緒可以理解為是程序中的控制流。同乙個程序內也就是說在同乙個位址空間內可以有多個控制流。也就是可以有多個線 程,他們共享位址空間。我們通常將程序視為是資源的集合,程序中有程式的正文 資料...
執行緒和程序
對於求職者,在面試的時候大多都會被問到 你對多執行緒了解麼?給我講講執行緒和程序的區別吧。在unix中,乙個程序可以理解為執行緒 位址空間 檔案描述符 資料,道破現實,其實就相當於老闆和員工,老闆就是程序,員工就是執行緒。老闆需要僱傭若干員工 執行緒 還要有辦公樓 位址空間 還要有若干的辦公裝置 檔...