W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
在Go語(yǔ)言中,表達(dá)式go f(x, y, z)會(huì)啟動(dòng)一個(gè)新的goroutine運(yùn)行函數(shù)f(x, y, z)。函數(shù)f,變量x、y、z的值是在原goroutine計(jì)算的,只有函數(shù)f的執(zhí)行是在新的goroutine中的。顯然,新的goroutine不能和當(dāng)前go線程用同一個(gè)棧,否則會(huì)相互覆蓋。所以對(duì)go關(guān)鍵字的調(diào)用協(xié)議與普通函數(shù)調(diào)用是不同的。
首先,讓我們看一下如果是C代碼新建一條線程的實(shí)現(xiàn)會(huì)是什么樣子的。大概會(huì)先建一個(gè)結(jié)構(gòu)體,結(jié)構(gòu)體里存f、x、y和z的值。然后寫一個(gè)help函數(shù),將這個(gè)結(jié)構(gòu)體指針作為輸入,函數(shù)體內(nèi)調(diào)用f(x, y, z)。接下來(lái),先填充結(jié)構(gòu)體,然后調(diào)用newThread(help, structptr)。其中help是剛剛那個(gè)函數(shù),它會(huì)調(diào)用f(x, y, z)。help函數(shù)將作為所有新建線程的入口函數(shù)。
這樣做有什么問題么?沒什么問題...只是這樣實(shí)現(xiàn)代價(jià)有點(diǎn)高,每次調(diào)用都會(huì)花上不少的指令。其實(shí)Go語(yǔ)言中對(duì)go關(guān)鍵字的實(shí)現(xiàn)會(huì)更加hack一些,避免了這么做。
先看看正常的函數(shù)調(diào)用,下面是調(diào)用f(1, 2, 3)時(shí)的匯編代碼:
MOVL $1, 0(SP)
MOVL $2, 4(SP)
MOVL $3, 8(SP)
CALL f(SB)
首先將參數(shù)1、2、3進(jìn)棧,然后調(diào)用函數(shù)f。
下面是go f(1, 2, 3)生成的代碼:
MOVL $1, 0(SP)
MOVL $2, 4(SP)
MOVL $3, 8(SP)
PUSHQ $f(SB)
PUSHQ $12
CALL runtime.newproc(SB)
POPQ AX
POPQ AX
對(duì)比一個(gè)會(huì)發(fā)現(xiàn),前面部分跟普通函數(shù)調(diào)用是一樣的,將參數(shù)存儲(chǔ)在正常的位置,并沒有新建一個(gè)輔助的結(jié)構(gòu)體。接下來(lái)的兩條指令有些不同,將f和12作為參數(shù)進(jìn)棧而不直接調(diào)用f,然后調(diào)用函數(shù)runtime.newproc
。
12是參數(shù)占用的大小。runtime.newproc
函數(shù)接受的參數(shù)分別是:參數(shù)大小,新的goroutine是要運(yùn)行的函數(shù),函數(shù)的n個(gè)參數(shù)。
在runtime.newproc
中,會(huì)新建一個(gè)??臻g,將棧參數(shù)的12個(gè)字節(jié)拷貝到新??臻g中并讓棧指針指向參數(shù)。這時(shí)的線程狀態(tài)有點(diǎn)像當(dāng)被調(diào)度器剝奪CPU后一樣,寄存器PC、SP會(huì)被保存到類似于進(jìn)程控制塊的一個(gè)結(jié)構(gòu)體struct G內(nèi)。f被存放在了struct G的entry域,后面進(jìn)行調(diào)度器恢復(fù)goroutine的運(yùn)行,新線程將從f開始執(zhí)行。
和前面說的如果用C實(shí)現(xiàn)的差別就在于,沒有使用輔助的結(jié)構(gòu)體,而runtime.newproc
實(shí)際上就是help函數(shù)。在函數(shù)協(xié)議上,go表達(dá)式調(diào)用就比普通的函數(shù)調(diào)用多四條指令而已,并且在實(shí)際上并沒有為go關(guān)鍵字設(shè)計(jì)一套特殊的東西。不得不說這個(gè)做法真的非常精妙!
總結(jié)一個(gè),go關(guān)鍵字的實(shí)現(xiàn)僅僅是一個(gè)語(yǔ)法糖衣而已,也就是:
go f(args)
可以看作
runtime.newproc(size, f, args)
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: