程序、執行緒與協程
程序
程序是指在系統中正在執行的一個應用程式,是CPU的最小工作單元。
程序執行中的三種狀態:就緒、執行、阻塞。建立和退出是描述產生和釋放的狀態。
在任務簡單or偏向CPU密集型(計算多IO少)時,程序的CPU利用率較高。隨著程式功能越來越複雜,常規的程式更加偏向IO密集型。但IO存在阻塞等待的特點,當一個程式獲得了CPU的時間片由就緒態切換至執行態,往往因為長時間等待IO而進入阻塞態,在IO操作完成後進入就緒態,在下一次獲得CPU時間片時才能完成。
無法即時完成的任務帶來大量的上下文切換代價與時間代價。
-
- 程序的上下文:當一個程序在執行時,CPU的所有暫存器中的值、程序的狀態以及堆疊中的內容被稱為該程序的上下文。
- 上下文切換:當核心需要切換到另一個程序時,它需要儲存當前程序的所有狀態,即儲存當前程序的上下文,以便在再次執行該程序時,能夠得到切換時的狀態並執行下去。
當人們開始思考使用更小的粒度提高程序單位時間的CPU利用率,執行緒應運而生。
執行緒
執行緒是CPU的最小執行單元(排程單元)。
程序作為執行緒的容器,按不同的功能,或想達到更高效率(如多個IO執行緒)的同一功能,可以考慮產生多個執行緒。
在CPU切換到本程序的時間段時,由於執行緒間共享程序的上下文,執行緒切換隻需要切換執行緒的上下文,而不需要切換另一片記憶體或者暫存器資源,在功能並行執行的同時降低了開銷。
-
- 開更多的執行緒不會導致本程序得到更多CPU的青睞
- 開更多的執行緒不會導致本程序得到更多CPU的青睞
程序才是CPU的最小作業單元(最小資源管理單元),開更多的執行緒不會導致本程序得到更多CPU的青睞,而是提高了CPU在本程序使用時間段的利用率。但是,本程序使用時間段的各執行緒優先順序是使用者可以自己設定的。
協程
雖然執行緒大幅的提高了CPU的效率,且能夠設定一定的優先順序,但是執行緒的資源片分配還是由CPU來管理的。
那麼能不能人為管理執行緒的資源分配(切換)呢?協程在語言層面實現了這一點。
協程=微執行緒=纖程
如同一個程序可以有很多執行緒一樣,一個執行緒可以有很多協程。
但是,協程不是被作業系統所管理的,沒有改變CPU最小執行單元是執行緒,協程是完全由程式所控制的(使用者態執行),不會產生上下文切換。
目前只有部分語言實現了協程:
- python的yield/send,當協程執行到yield關鍵字時,會暫停在那一行,等到主執行緒呼叫send方法傳送了資料,協程才會接到資料繼續執行。
- Lua從5.0版本開始使用協程,通過擴充套件庫coroutine來實現。
- Go語言對協程的實現非常強大而簡潔,可以輕鬆建立成百上千個協程併發執行。
- Java語言並沒有對協程的原生支援,但是某些開源框架模擬出了協程的功能,有興趣的小夥伴可以看一看Kilim框架的原始碼:https://github.com/kilim/kilim