執行緒、程序和協成對比
講述執行緒、程序和協成?
1)為什麼引入:
作業系統可以同時執行多個任務,引入了執行緒,程序和協成
2)定義:
執行緒: 可以理解成執行程式碼的分支,執行緒是執行對應的程式碼的,cpu會排程對應的執行緒去工作,也可以說執行緒是cpu排程的基本單位(工作原理)
程序: 通俗理解一個執行起來的程式或者軟體叫做程序
如何理解程序:把程序想成現實生活中的公司,公司可以給員工提供辦公資源(辦公桌椅,辦公電腦等資源), 真正幹活的是員工,所以員工可以想成執行緒,公司就是程序
協成:又稱為微執行緒,也稱為使用者級執行緒,在不開闢執行緒的基礎上完成多工,在def裡面只看到一個yield關鍵字可以理解程是協程(理解), 在單執行緒的基礎上可以完成多工,多個任務按照一定順序交替執行(目的)
3)使用:
程序、執行緒和協成的使用對比
2.1 執行緒是cpu排程的基本單位,通過執行緒去執行程序中程式碼, 執行緒是執行程式碼的分支
2.2 程序是作業系統資源分配的基本單位,每啟動一個程序都需要向作業系統索要執行資源,預設一個程序只有一個執行緒,執行緒是依附在程序裡面的
2.3 多程序開發比單程序多執行緒開發穩定性要強,但是多程序開發比多執行緒開發資源開銷要大
2.4 多程序開發某個程序死了不會影響其它程序的執行,但是多執行緒開發該程序死了那麼這些執行緒都要進行銷燬
2.5 程序之間不共享全域性變數,執行緒之間共享全域性變數,但是執行緒要注意資源競爭的問題
執行緒之間共享全域性變數:
同步就是協同步調,按預定的先後次序進行執行執行緒同步可以解決共享全域性變數的問題
從而引入了互斥鎖,互斥鎖確保了某段關鍵程式碼只能由一個執行緒從頭到尾完整地執行,在使用過程中要避免出現死鎖
程序之間不共享全域性變數:
多程序之間不共享全域性變數,為了程序間的通訊,引入Queue這個類
2.6 先有程序,然後程序可以建立執行緒,執行緒是依附在程序裡面的,執行緒裡面可以包含多個協程
2.7 多執行緒開發執行緒之間執行是無序的,協程之間執行按照一定順序交替執行
2.8 協程以後主要用在網路爬蟲和網路請求,開闢一個協程大概需要5k空間,開闢一個執行緒需要512k空間, 開闢一個程序佔用資源最多
附錄:
對於執行緒的使用:
1.執行緒之間執行是無序(對比中已包含)
2.主執行緒會等待所有的子執行緒執行完成以後程式再退出,daemon=True 表示守護主執行緒,主執行緒退出子執行緒直接銷燬不再執行對應的程式碼
3.多執行緒共享全域性變數(對比中已包含)
4.互斥鎖: 能保證同一時刻只有一個執行緒去執行程式碼,具體那個執行緒搶到鎖我們決定不了,但是加上互斥鎖多工瞬間變成單任務變成單任務效能會下降(對比中已包含)
5.死鎖:一直等待對方釋放鎖的情景就叫做死鎖,工作中避免死鎖的出現,要在適當的地方釋放鎖(對比中已包含)
對於程序的使用:
1.多程序之間不共享全域性變數,為了程序間的通訊,引入Queue這個類(對比中已包含)
2.向佇列裡面放入資料統一put方法,獲取資料的使用同一使用get方法
3.主程序會等待所有的子程序執行完成以後程式再退出,設定守護主程序,主程序退出後子程序直接銷燬 sub_process.daemon = True
主程序退出之前先讓子程序直接銷燬,然後主程序就可以退出了:sub_process.terminate()
通過程序池完成對應的任務
同步執行:一個任務執行完成另外一個任務才能執行 pool.apply(copy_work) 資源競爭時使用
使用非同步方式用程序池執行對應的任務:pool.apply_async(copy_work)
5.建立程序池中的queue時,使用非同步執行對應的任務,執行非同步任務會返回一個應用結果物件,這個物件裡面有一個wait()方法可以等待非同步任務執行完成以後程式碼再繼續往下執行
對於協成的使用:
gevent封裝是greenlet,可以根據耗時操作自動完成協程之間的切換執行
打補丁,讓gevent框架識別耗時操作,比如:time.sleep,網路請求延時,monkey.patch_all()
建立協程指定對應的任務
*args: 以位置方式傳參
**kwargs: 以關鍵字方式傳參
g1 = gevent.spawn(download_img, img_url1, “1.jpg”)
主執行緒等待所有的協程執行完成以後程式再退出
gevent.joinall([g1, g2, g3])
更多見:https://blog.csdn.net/sinat_41912529/article/details/80306582