99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Go語言 關鍵字:go

2018-07-25 17:23 更新

在Go語言中,表達式go f(x, y, z)會啟動一個新的goroutine運行函數(shù)f(x, y, z)。函數(shù)f,變量x、y、z的值是在原goroutine計算的,只有函數(shù)f的執(zhí)行是在新的goroutine中的。顯然,新的goroutine不能和當前go線程用同一個棧,否則會相互覆蓋。所以對go關鍵字的調用協(xié)議與普通函數(shù)調用是不同的。

首先,讓我們看一下如果是C代碼新建一條線程的實現(xiàn)會是什么樣子的。大概會先建一個結構體,結構體里存f、x、y和z的值。然后寫一個help函數(shù),將這個結構體指針作為輸入,函數(shù)體內調用f(x, y, z)。接下來,先填充結構體,然后調用newThread(help, structptr)。其中help是剛剛那個函數(shù),它會調用f(x, y, z)。help函數(shù)將作為所有新建線程的入口函數(shù)。

這樣做有什么問題么?沒什么問題...只是這樣實現(xiàn)代價有點高,每次調用都會花上不少的指令。其實Go語言中對go關鍵字的實現(xiàn)會更加hack一些,避免了這么做。

先看看正常的函數(shù)調用,下面是調用f(1, 2, 3)時的匯編代碼:

    MOVL    $1, 0(SP)
    MOVL    $2, 4(SP)
    MOVL    $3, 8(SP)
    CALL    f(SB)

首先將參數(shù)1、2、3進棧,然后調用函數(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

對比一個會發(fā)現(xiàn),前面部分跟普通函數(shù)調用是一樣的,將參數(shù)存儲在正常的位置,并沒有新建一個輔助的結構體。接下來的兩條指令有些不同,將f和12作為參數(shù)進棧而不直接調用f,然后調用函數(shù)runtime.newproc

12是參數(shù)占用的大小。runtime.newproc函數(shù)接受的參數(shù)分別是:參數(shù)大小,新的goroutine是要運行的函數(shù),函數(shù)的n個參數(shù)。

runtime.newproc中,會新建一個??臻g,將棧參數(shù)的12個字節(jié)拷貝到新??臻g中并讓棧指針指向參數(shù)。這時的線程狀態(tài)有點像當被調度器剝奪CPU后一樣,寄存器PC、SP會被保存到類似于進程控制塊的一個結構體struct G內。f被存放在了struct G的entry域,后面進行調度器恢復goroutine的運行,新線程將從f開始執(zhí)行。

和前面說的如果用C實現(xiàn)的差別就在于,沒有使用輔助的結構體,而runtime.newproc實際上就是help函數(shù)。在函數(shù)協(xié)議上,go表達式調用就比普通的函數(shù)調用多四條指令而已,并且在實際上并沒有為go關鍵字設計一套特殊的東西。不得不說這個做法真的非常精妙!

總結一個,go關鍵字的實現(xiàn)僅僅是一個語法糖衣而已,也就是:

    go f(args)

可以看作

    runtime.newproc(size, f, args)

links


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號