go是多線程還是協(xié)程?
3.1 概念
在go程序中,由輕量級(jí)線程實(shí)現(xiàn),由Go運(yùn)行時(shí)(runtime)管理。
3.2 與進(jìn)程、線程的區(qū)別
1)進(jìn)程擁有自己獨(dú)立的堆棧,既不共享堆,也不共享?xiàng)!J怯刹僮飨到y(tǒng)調(diào)度的。
2)線程擁有自己獨(dú)立的棧和共享的堆,共享堆,不共享?xiàng)#怯刹僮飨到y(tǒng)調(diào)度。
2)協(xié)程共享堆,不共享?xiàng)#瑓f(xié)程是由程序員在協(xié)程的代碼中顯示調(diào)度。
3.3 主線程和協(xié)程的關(guān)系
3.4 協(xié)程比線程輕量的原因
3.4.1 線程并發(fā)的流程
線程是內(nèi)核對(duì)外提供的服務(wù),應(yīng)用程序可以通過系統(tǒng)調(diào)用讓內(nèi)核啟動(dòng)線程,由內(nèi)核來負(fù)責(zé)線程的調(diào)度和切換。線程在等待I/O操作時(shí)線程變?yōu)閡nrunnable狀態(tài)會(huì)觸發(fā)上下文切換。現(xiàn)代操作系統(tǒng)一般都采用搶占式調(diào)度,上下文切換一般發(fā)生在時(shí)鐘中斷和系統(tǒng)調(diào)用返回前,調(diào)度器計(jì)算當(dāng)前線程的時(shí)間片,如果需要切換就從隊(duì)列中選出一個(gè)目標(biāo)線程,保存當(dāng)前線程的環(huán)境,并且恢復(fù)目標(biāo)線程的運(yùn)行環(huán)境,最典型的就是切換ESP指向目標(biāo)線程內(nèi)核堆棧,將EIP指向目標(biāo)線程上次被調(diào)度出時(shí)的指令地址。
3.4.2 協(xié)程并發(fā)的流程
不依賴操作系統(tǒng)和其提供的線程,golang自己實(shí)現(xiàn)的CSP并發(fā)模型:M,P,G
go協(xié)程也叫用戶態(tài)線程,協(xié)程之間的切換發(fā)生在用戶態(tài)。在用戶態(tài)沒有時(shí)鐘中斷、系統(tǒng)調(diào)用等機(jī)制,因此效率高。
3.5 go協(xié)程占用內(nèi)存少的原因
執(zhí)行g(shù)o協(xié)程只需要極少的棧內(nèi)存(大概4~5KB),默認(rèn)情況下,線程棧的大小為1MB。
goroutine就是一段代碼,一個(gè)函數(shù)入口,以及在堆上分配的一個(gè)堆棧。所以我們可以輕松創(chuàng)建上萬個(gè)goroutine,但他們并不是被操作系統(tǒng)調(diào)度執(zhí)行的。