1.多線程、多進程、多協程
進程:一個運行的程序,進程是系統調度和分配的最小單位,擁有自己獨立的空間內存,進程之間不共享資源。
線程:調度執行的最小單位,依賴於進程,一個進程至少有一個線程,並且同一個進程內的線程之間共享資源,大大提升了程序運行速度,切換由系統調度。
協程:一種用戶態的輕量級線程,切換由用戶調度,擁有自己的上下文和棧,切換時將寄存器上下文和棧保存在別的地方,切換回來時,恢復先前的寄存器上下文和棧,直接操作棧基本沒有內核的消耗,
所以切換速度較快。
2.多線程競爭
線程是獨立的,多線程之間共享資源,當多個線程訪問同一資源時,數據同時被多個線程所占有,導致數據混亂,即數據不安全。為了解決這個問題,那就有了鎖。
鎖的好處,確保了某段代碼只能從頭到尾都只能被一個線程占有。
鎖的壞處,阻止了線程的並發性,大大降低了程序的運行速度。
3.鎖
鎖是python提供的對多線程進行控制的對象,有互斥鎖,可重入鎖,死鎖。
死鎖,若干子線程在資源競爭時,都在等待對方解除對某一資源的占用,導致程序無法運行下去。
GIL鎖,全局解釋器鎖(golbal interpreter lock)只有在cpython中存在,作用是限制多線程的同時執行,同一時間只允許一個線程的運行。在python中常使用協程來代替進程,協程是輕量級的進程,
並且由用戶控制。
互斥鎖,同一個進程中多線程共享資源,為了達到數據安全的效果,同一時間只能有一個線程去訪問某一資源,后續的線程必須等待前一個線程訪問過后才能繼續訪問這一資源。
4.同步,異步,非阻塞
任務
同步,多個任務按順序執行
異步,多個任務同時執行,並且存在某個任務需要另一個任務執行之后的結果作為條件,這叫回調
代碼
阻塞,執行卡住,不再繼續往下執行
非阻塞,執行不會卡住,可以繼續執行
5.僵屍進程,孤兒進程
1.僵屍進程,子進程比父進程結束的早,沒有被收回,且沒有釋放所占有的資源
2.孤兒進程,父進程結束的比子進程早,子進程還在運行,這類進程后續會被init進程接管,完成狀態收集工作
3.對僵屍進程的解決方法 1.fork兩次讓孫子進程去執行子進程的任務
2.用wait()使父進程阻塞
3.使用信號量,signal handler 中調用waitnid
6.進程
進程是程序的一次動態執行過程
創建,准備,運行,阻塞,結束
7.python中多線程與多進程的使用場景
多進程cpu密集型操作
多線程io密集型操作
8.協程
asyncio
實現的功能
1.異步網絡操作
2.並發
3.協程
關鍵字說明
1.event_loop 事件循環,程序開啟一個無限循環,當實現一定條件時,執行此事件
2.coroutine 協程,指async關鍵字定義的函數,調用不會立即執行,而是會返回一個協程對象,只有注冊到事件循環中后,由事件循環調用
3.task任務 對協程對象的屬性和狀態進行包裝
4.future 與task沒有本質上的區別
5.async/await關鍵字 async定義協程函數,await用於調用掛起阻塞的異步調用接口
一個協程對象的定義
async def coroutine():
pass
c = conroutine()
pool = asyncio.get_event_loop() #創建事件循環
pool.run_until_complete(c) #將協程對象注冊到事件循環中,並開啟事件循環
一個task對象的定義
loop = asyncio.get_event_loop()
task = loop.create_task(conroutine) #創建一個task任務,包裝協程對象,保存了協程運行后的狀態,用於未來獲取協程的結果,也可通過asyncio.ensure_future(conroutine)創建task任務
pool.run_utile_complete(task)
task加入到事件循環之前狀態為pending,之后為finished
對task任務添加回調函數
def callback(future):
pass
task.add_done_callback()
await 掛起耗時操作或阻塞,將協程的控制權交出,以便事件循環調用其他協程
關於並發與並行
並發:同時具有多個活動的系統
並行:用多個並發使一個系統運行的更快速。並行可以在操作系統的多個抽象層次運用
通俗講,並發,多個任務需要同時進行,並行,同一時刻有多個任務執行。
並發
tasks = [
asyncio.ensure_future(coroutine1),
asyncio.ensure_future(coroutine2),
asyncio.ensure_future(coroutine3)
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks)) #asyncio.gather(*tasks)