先理解下進程斤儿、線程跟協(xié)程的概念:
進程
?? 計算機的操作系統(tǒng)模式是一種多任務(wù)系統(tǒng)
,操作系統(tǒng)接管了所有的硬件資源腮考,并且本身運行在一個受硬件保護的級別雇毫。所有的應(yīng)用程序都以進程(process)
的方式運行在比操作系統(tǒng)權(quán)限更低的級別,每個進程都有自己獨立的地址空間踩蔚,使得進程之間的地址空間相互隔離棚放。CPU由操作系統(tǒng)統(tǒng)一進行分配,每個進程根據(jù)進程的優(yōu)先級的高低都有機會得到CPU,但是如果允許時間超出了一定的時間馅闽,操作系統(tǒng)會暫停該進程飘蚯,將CPU資源分配給其他等待的進程。這種CPU的分配方式即所謂的搶占式
福也,操作系統(tǒng)可以強制剝奪CPU資源并且分配給它認為目前最需要的進程局骤。如果操作系統(tǒng)分配給每個進程的時間都很短,即CPU在多個進程間快速地切換暴凑,從而造成了很多進程都在同時運行的假象峦甩。
線程
??線程
有時被稱為輕量級進程(Lightweight Process)
,是程序執(zhí)行流的最小單元,一個標(biāo)準(zhǔn)的線程由線程ID,當(dāng)前指令指針(PC)现喳、寄存器集合和堆棧組成凯傲,通常意義上,一個進程??一個到多個線程組成嗦篱,各個線程之間共享程序的內(nèi)存空間(包括代碼段冰单、數(shù)據(jù)段、堆等)及一些進程級的資源(如打開文件和信號)灸促。一個經(jīng)典的線程與進程的關(guān)系如圖1-8所示:
go協(xié)程
??協(xié)程(coroutine)是Go語言中的輕量級線程
實現(xiàn)诫欠,由Go運行時(runtime)管理涵卵。
進程、線程荒叼、協(xié)程的關(guān)系和區(qū)別:
進程擁有自己獨立的堆和棧轿偎,既不共享堆,亦不共享棧甩挫,進程由操作系統(tǒng)調(diào)度贴硫。
線程擁有自己獨立的棧和共享的堆,共享堆伊者,不共享棧英遭,線程亦由操作系統(tǒng)調(diào)度(標(biāo)準(zhǔn)線程是的)。
協(xié)程和線程一樣共享堆亦渗,不共享棧挖诸,協(xié)程由程序員在協(xié)程的代碼里顯示調(diào)度。
并發(fā)與并行(Concurrency and Parallelism)
??并發(fā)是指程序的邏輯結(jié)構(gòu)法精。非并發(fā)的程序就是一根竹竿捅到底多律,只有一個邏輯控制流,也就是順序執(zhí)行的(Sequential)程序搂蜓,在任何時刻狼荞,程序只會處在這個邏輯控制流的某個位置。而如果某個程序有多個獨立的邏輯控制流帮碰,也就是可以同時處理(deal)多件事情相味,我們就說這個程序是并發(fā)的。這里的“同時”殉挽,并不一定要是真正在時鐘的某一時刻(那是運行狀態(tài)而不是邏輯結(jié)構(gòu))丰涉,而是指:如果把這些邏輯控制流畫成時序流程圖,它們在時間線上是可以重疊的斯碌。
??并行是指程序的運行狀態(tài)一死。如果一個程序在某一時刻被多個CPU流水線同時進行處理,那么我們就說這個程序是以并行的形式在運行傻唾。(嚴(yán)格意義上講投慈,我們不能說某程序是“并行”的,因為“并行”不是描述程序本身冠骄,而是描述程序的運行狀態(tài)伪煤,但這篇小文里就不那么咬文嚼字,以下說到“并行”的時候猴抹,就是指代“以并行的形式運行”)顯然,并行一定是需要硬件支持的锁荔。
??而且不難理解:
- 并發(fā)是并行的必要條件蟀给,如果一個程序本身就不是并發(fā)的蝙砌,也就是只有一個邏輯控制流,那么我們不可能讓其被并行處理跋理。
- 并發(fā)不是并行的充分條件择克,一個并發(fā)的程序,如果只被一個CPU流水線進行處理(通過分時)前普,那么它就不是并行的肚邢。
為什么協(xié)程比線程輕量?
- go協(xié)程調(diào)用跟切換比線程效率高
線程并發(fā)執(zhí)行流程:
??線程是內(nèi)核對外提供的服務(wù)拭卿,應(yīng)用程序可以通過系統(tǒng)調(diào)用讓內(nèi)核啟動線程骡湖,由內(nèi)核來負責(zé)線程調(diào)度和切換。線程在等待IO操作時線程變?yōu)閡nrunnable狀態(tài)會觸發(fā)上下文切換【瘢現(xiàn)代操作系統(tǒng)一般都采用搶占式調(diào)度响蕴,上下文切換一般發(fā)生在時鐘中斷和系統(tǒng)調(diào)用返回前,調(diào)度器計算當(dāng)前線程的時間片惠桃,如果需要切換就從運行隊列中選出一個目標(biāo)線程浦夷,保存當(dāng)前線程的環(huán)境,并且恢復(fù)目標(biāo)線程的運行環(huán)境辜王,最典型的就是切換ESP指向目標(biāo)線程內(nèi)核堆棧劈狐,將EIP指向目標(biāo)線程上次被調(diào)度出時的指令地址。
go協(xié)程并發(fā)執(zhí)行流程:
??不依賴操作系統(tǒng)和其提供的線程呐馆,golang自己實現(xiàn)的CSP并發(fā)模型實現(xiàn):M, P, G
??go協(xié)程也叫用戶態(tài)線程肥缔,協(xié)程之間的切換發(fā)生在用戶態(tài)。在用戶態(tài)沒有時鐘中斷摹恰,系統(tǒng)調(diào)用等機制,因此效率高
- 2.go協(xié)程占用內(nèi)存少
??執(zhí)行g(shù)o協(xié)程只需要極少的棧內(nèi)存(大概是4~5KB)辫继,默認情況下,線程棧的大小為1MB俗慈。
??goroutine就是一段代碼姑宽,一個函數(shù)入口,以及在堆上為其分配的一個堆棧闺阱。所以它非常廉價炮车,我們可以很輕松的創(chuàng)建上萬個goroutine,但它們并不是被操作系統(tǒng)所調(diào)度執(zhí)行酣溃。
參考資料
- Goroutine(協(xié)程)為何能處理大并發(fā)
https://studygolang.com/articles/4535
- Goroutine(協(xié)程)為何能處理大并發(fā)
- Coroutine及其實現(xiàn)
http://www.cnblogs.com/foxmailed/archive/2014/01/08.html
- Coroutine及其實現(xiàn)
- goroutine背后的系統(tǒng)知識
http://www.sizeofvoid.net/goroutine-under-the-hood/
- goroutine背后的系統(tǒng)知識
- [Go的CSP并發(fā)模型實現(xiàn):M, P, G
https://www.cnblogs.com/sunsky303/p/9115530.html
- [Go的CSP并發(fā)模型實現(xiàn):M, P, G