參考自《go專家編程》
Go協(xié)程所實(shí)現(xiàn)的是M:N的線程模型,M個(gè)協(xié)程運(yùn)行在N個(gè)線程中。
1. MPG模型
Go協(xié)程中有三個(gè)關(guān)鍵實(shí)體:
- M(machine): 工作線程,由操作系統(tǒng)調(diào)度。應(yīng)該就是通常所說的內(nèi)核線程。
- P(processor): 處理器(非CPU),代表著運(yùn)行Go代碼的必要資源,以及調(diào)度goroutine的能力。個(gè)人覺得可以當(dāng)作擁有自主調(diào)度權(quán)的算法模塊,用于工作竊?。╳ork stealing)。
- G(gooutine): Go協(xié)程,輕量級(jí)用戶線程。主要包含執(zhí)行棧和調(diào)度管理器。這里的調(diào)度管理器指的是,統(tǒng)一并管理調(diào)度資源,等待被調(diào)度。
其關(guān)系如下圖:

關(guān)于M的數(shù)目:
M的個(gè)數(shù)是根據(jù)實(shí)際情況自行創(chuàng)建的,一般稍大于P的個(gè)數(shù),為了保證runtime包的內(nèi)置任務(wù)的運(yùn)行。在運(yùn)行中不夠用時(shí),也會(huì)再重新創(chuàng)建一個(gè)。
關(guān)于P的數(shù)目:
P的個(gè)數(shù)默認(rèn)為CPU的核數(shù),在IO密集的場景下可以適當(dāng)提高P的個(gè)數(shù)。設(shè)置方式有兩種,例:
設(shè)置環(huán)境變量:
export GOMAXPROCS=80
runtime.GOMAXPROCS()方法:
runtime.GOMAXPROCS(80)
- 全局
runqueue隊(duì)列
全局隊(duì)列由多個(gè)處理器共享,訪問通過互斥鎖來完成。
處理器P中的協(xié)程G額外再創(chuàng)建的協(xié)程會(huì)加入到本地的runqueues中。
兩種情況下會(huì)放入全局隊(duì)列中:1. 本地隊(duì)列已滿 2. 阻塞的協(xié)程被喚醒
全局隊(duì)列會(huì)被處理器P周期性的摘取來調(diào)度。
2. 調(diào)度策略
- 隊(duì)列輪轉(zhuǎn)
每個(gè)處理器
P維護(hù)著一個(gè)協(xié)程G的隊(duì)列,處理器依次將協(xié)程G調(diào)度到M中執(zhí)行。
此外,每個(gè)P周期性的查看全局隊(duì)列中是否有G將其調(diào)度到M中執(zhí)行。
(全局隊(duì)列中的G主要來自系統(tǒng)調(diào)用中恢復(fù)的G。)
- 系統(tǒng)調(diào)用
前情提要:1.如一個(gè)線程進(jìn)行系統(tǒng)調(diào)用會(huì)進(jìn)入阻塞狀態(tài),一個(gè)協(xié)程進(jìn)行系統(tǒng)調(diào)用也會(huì)導(dǎo)致線程進(jìn)入阻塞狀態(tài)。2. 前面提到
M的數(shù)量會(huì)稍大于P的數(shù)量,多出來的M在系統(tǒng)調(diào)用時(shí)就會(huì)發(fā)揮作用。3. 當(dāng)M不夠用時(shí),會(huì)再創(chuàng)建M。
當(dāng)
M0運(yùn)行的G0產(chǎn)生系統(tǒng)調(diào)用時(shí),M0將會(huì)釋放P,進(jìn)而某個(gè)冗余的M1將會(huì)獲取P,繼而執(zhí)行P中所剩下的G。這時(shí)候M0進(jìn)入阻塞,而M1接替M0的工作。
所以,在開發(fā)中一定要避免頻繁的系統(tǒng)調(diào)用?。。∫坏┱{(diào)用結(jié)束的速度跟不上調(diào)用產(chǎn)生的速度,那么系統(tǒng)資源將會(huì)有嚴(yán)重的浪費(fèi)!
那
G0的系統(tǒng)調(diào)用結(jié)束后呢?
此時(shí)根據(jù)M0是否能獲取到P來對(duì)G0作出不同的處理:1. 如果有空閑的P,則獲取繼續(xù)執(zhí)行G0。2. 如果沒有空閑的P,將把G0放入全局隊(duì)列,等待被其他的P調(diào)度。M0將進(jìn)入緩存池。
- 工作量竊取
工作量竊取是為了實(shí)現(xiàn)
P的負(fù)載均衡。
當(dāng)當(dāng)前P沒有協(xié)程調(diào)度,并且全局隊(duì)列中也沒有需要調(diào)度的協(xié)程時(shí),會(huì)從另一個(gè)正在運(yùn)行的處理器P中偷取協(xié)程,每次偷取一半。
- 搶占式調(diào)度
該機(jī)制是為了避免某個(gè)協(xié)程長時(shí)間執(zhí)行,而阻礙到其他協(xié)程被調(diào)度。
調(diào)度器監(jiān)控每個(gè)協(xié)程的執(zhí)行時(shí)間,當(dāng)其執(zhí)行時(shí)間過長且有其他協(xié)程在等待是,會(huì)把協(xié)程暫停,轉(zhuǎn)而調(diào)度等待的協(xié)程,達(dá)到類似時(shí)間片輪轉(zhuǎn)的效果。