最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解go語言是如何實(shí)現(xiàn)協(xié)程的

 更新時(shí)間:2024年04月19日 09:36:13   作者:shark_chili  
go語言的精華就在于協(xié)程的設(shè)計(jì),只有理解協(xié)程的設(shè)計(jì)思想和工作機(jī)制,才能確保我們能夠完全的利用協(xié)程編寫強(qiáng)大的并發(fā)程序,所以本文將給大家介紹了go語言是如何實(shí)現(xiàn)協(xié)程的,文中有詳細(xì)的代碼講解,需要的朋友可以參考下

寫在文章開頭

go語言的精華就在于協(xié)程的設(shè)計(jì),只有理解協(xié)程的設(shè)計(jì)思想和工作機(jī)制,才能確保我們能夠完全的利用協(xié)程編寫強(qiáng)大的并發(fā)程序。

詳解協(xié)程工作機(jī)制和實(shí)現(xiàn)

協(xié)程示例

正式介紹底層之前,我們給出一段協(xié)程的代碼示例,可以看到筆者開啟一個(gè)協(xié)程進(jìn)行函數(shù)內(nèi)部調(diào)用:

func foo1() {
 fmt.Println("foo1 調(diào)用 foo2")
 foo2()
}

func foo2() {
 fmt.Println("foo2調(diào)用foo3")
 foo3()
}

func foo3() {
 fmt.Println("foo3 執(zhí)行了")
}

func main() {
 //設(shè)置WaitGroup等待協(xié)程結(jié)束
 var wg sync.WaitGroup
 wg.Add(1)

 go func() {
  foo1()
  defer wg.Done()
 }()

 //等待上述協(xié)程運(yùn)行結(jié)束
 wg.Wait()
}

運(yùn)行結(jié)果如下:

foo1 調(diào)用 foo2
foo2調(diào)用foo3
foo3 執(zhí)行了

結(jié)合debug我們可以看到當(dāng)前協(xié)程的調(diào)用棧幀,在函數(shù)調(diào)用前插入一個(gè)goexit的東西,結(jié)合這一點(diǎn)我們開始對(duì)協(xié)程的深入剖析:

在這里插入圖片描述

協(xié)程實(shí)現(xiàn)結(jié)構(gòu)

go語言的協(xié)程結(jié)構(gòu)為:

  • 通過一個(gè)stack記錄其高地址和低地址。
  • 通過schedsp(即stackpointer)棧幀的指針程序計(jì)數(shù)器pc(指向下一條運(yùn)行的指令).
  • 采用goid生成唯一標(biāo)識(shí)。
  • 然后再用atomicstatus記錄其執(zhí)行狀態(tài)。

基于這幾點(diǎn)我們結(jié)合上述的代碼給出協(xié)程的底層結(jié)構(gòu),如下圖所示,當(dāng)前協(xié)程的stack記錄整個(gè)foo1函數(shù)的高低地址,假設(shè)我們當(dāng)前的協(xié)程go來到foo2函數(shù)準(zhǔn)備調(diào)用foo3函數(shù),我們的sched中的sp即stackpointer記錄foo2的指針,同時(shí)因?yàn)?code>foo2內(nèi)部會(huì)調(diào)用foo3所以程序計(jì)數(shù)器pc記錄著調(diào)用foo3的指令。

最后因?yàn)閰f(xié)程都是由線程調(diào)度的,所以協(xié)程的內(nèi)部也有一個(gè)變量記錄著當(dāng)前線程的指針m:

到此我們了解了協(xié)程核心結(jié)構(gòu),同時(shí)我們也在runtime2.go這一文件中即給出上述所說的核心變量:

type g struct {
 //記錄棧幀的高地址和低地址
 stack       stack   // offset known to runtime/cgo
 //......
 m         *m //執(zhí)行當(dāng)前協(xié)程的線程指針
 //記錄當(dāng)前堆棧的指針以及下一條指令的運(yùn)行地址
 sched     gobuf
 atomicstatus atomic.Uint32
 goid         uint64
 
 //......
}

步入stack可以看到lohi兩個(gè)專門記錄棧幀高低地址的指針:

type stack struct {
 lo uintptr
 hi uintptr
}

對(duì)應(yīng)的我們也給出sched 的類型gobuf,可以看到sppc兩個(gè)核心指針變量:

type gobuf struct {
 
 sp   uintptr
 pc   uintptr
 //......
}

談?wù)刧o語言對(duì)于線程的抽象

上文我們提出線程的用m指針記錄,如下源碼所示,我們都知道在go語言中每個(gè)線程都會(huì)從一個(gè)協(xié)程隊(duì)列中獲取協(xié)程執(zhí)行,所以執(zhí)行時(shí)它會(huì)用curg記錄當(dāng)前運(yùn)行的協(xié)程,然后通過id對(duì)自己進(jìn)行唯一標(biāo)識(shí),而mOS則是及記錄當(dāng)前操作系統(tǒng)信息,這其中最核心的就是g0它就是每一個(gè)線程的操作調(diào)度器:

type m struct {
 g0      *g     // goroutine with scheduling stack
 id            int64 
 
 curg          *g       // current running goroutine
 
 mOS

}

了解整體結(jié)構(gòu)之后我們?cè)賮砹牧膅o語言線程的g0棧是如何工作的,如下圖所示,每一個(gè)g0棧都會(huì)通過schedule開始工作:

  • 通過execute從協(xié)程隊(duì)列中獲取任務(wù)。
  • 調(diào)用gogo方法在協(xié)程調(diào)用前插入go exit指針?biāo)涗沢0棧幀,這個(gè)指針就是用于協(xié)程執(zhí)行退出或者掛起是可以通過這個(gè)指針跳回g0棧。
  • 然后就是執(zhí)行當(dāng)前協(xié)程。
  • 協(xié)程執(zhí)行完成切換回g0棧,重新調(diào)用schedule方法再次從步驟1開始執(zhí)行,由此構(gòu)成一個(gè)循環(huán)。

這里我們也給出asm_amd64.s中關(guān)于gogo的匯編代碼,可以看到gobuf_sp方法它會(huì)記錄當(dāng)前stack pointer也就是我們上文針對(duì)g0所說的g0棧地址:

TEXT gogo<>(SB), NOSPLIT, $0
 get_tls(CX)
 MOVQ DX, g(CX)
 MOVQ DX, R14  // set the g register
 //記錄g0棧地址
 MOVQ gobuf_sp(BX), SP // restore SP
 MOVQ gobuf_ret(BX), AX
 MOVQ gobuf_ctxt(BX), DX
 MOVQ gobuf_bp(BX), BP
 MOVQ $0, gobuf_sp(BX) // clear to help garbage collector
 MOVQ $0, gobuf_ret(BX)
 MOVQ $0, gobuf_ctxt(BX)
 MOVQ $0, gobuf_bp(BX)
 MOVQ gobuf_pc(BX), BX
 JMP BX

小結(jié)

自此我們從go語言底層實(shí)現(xiàn)的角度完整的剖析的協(xié)程與線程的關(guān)系和實(shí)現(xiàn),希望對(duì)你有幫助。

以上就是詳解go語言是如何實(shí)現(xiàn)協(xié)程的的詳細(xì)內(nèi)容,更多關(guān)于go實(shí)現(xiàn)協(xié)程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • LRU?LFU?TinyLFU緩存算法實(shí)例詳解

    LRU?LFU?TinyLFU緩存算法實(shí)例詳解

    這篇文章主要為大家介紹了LRU?LFU?TinyLFU緩存算法實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Go標(biāo)準(zhǔn)庫net/http包的實(shí)現(xiàn)

    Go標(biāo)準(zhǔn)庫net/http包的實(shí)現(xiàn)

    net/http是Go官方自帶的 HTTP 框架,不用裝任何第三方庫,本文就來詳細(xì)的介紹一下Go標(biāo)準(zhǔn)庫net/http包的實(shí)現(xiàn),感興趣的可以了解一下
    2026-03-03
  • Gin中數(shù)據(jù)解析和綁定的幾種方法實(shí)現(xiàn)

    Gin中數(shù)據(jù)解析和綁定的幾種方法實(shí)現(xiàn)

    本文主要介紹了Gin中數(shù)據(jù)解析和綁定的幾種方法實(shí)現(xiàn),包括Json數(shù)據(jù)、表單數(shù)據(jù)和URI數(shù)據(jù),每種類型的數(shù)據(jù)都有其特定的解析和綁定方法,下面就一起來了解一下
    2025-11-11
  • Golang中字符串(string)與字節(jié)數(shù)組([]byte)一行代碼互轉(zhuǎn)實(shí)例

    Golang中字符串(string)與字節(jié)數(shù)組([]byte)一行代碼互轉(zhuǎn)實(shí)例

    golang語言本身就是c的工具集,開發(fā)c的程序用到的大部分結(jié)構(gòu)體,內(nèi)存管理,攜程等,golang基本都有,下面這篇文章主要給大家介紹了關(guān)于Golang中字符串(string)與字節(jié)數(shù)組([]byte)一行代碼互轉(zhuǎn)的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • go編譯so庫讓python引用編譯后沒有.h文件的問題

    go編譯so庫讓python引用編譯后沒有.h文件的問題

    有時(shí)python需要引用go的一些開源庫,這時(shí)就需要go編譯成python可調(diào)用的庫,本文給大家介紹了go編譯so庫讓python引用,編譯后沒有.h文件的問題,需要的朋友可以參考下
    2024-02-02
  • golang操作Redis的實(shí)現(xiàn)示例

    golang操作Redis的實(shí)現(xiàn)示例

    本文主要介紹了golang操作Redis的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • Go 語言中關(guān)于接口的三個(gè)

    Go 語言中關(guān)于接口的三個(gè)

    這篇文章主要介紹了Go 語言中關(guān)于接口的三個(gè)"潛規(guī)則",本文通過實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Go通道channel通過通信共享內(nèi)存

    Go通道channel通過通信共享內(nèi)存

    這篇文章主要為大家介紹了Go通道channel通過通信共享內(nèi)存示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Windows下安裝VScode 并使用及中文配置方法

    Windows下安裝VScode 并使用及中文配置方法

    這篇文章主要介紹了Windows下安裝VScode 并使用及中文配置的方法詳解,本文通過圖文并茂的形式給大家介紹,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Go語言map實(shí)現(xiàn)順序讀取

    Go語言map實(shí)現(xiàn)順序讀取

    當(dāng)我們遍歷 map 時(shí),那就是輸出的鍵值對(duì)順序是不確定的,本文主要介紹了Go語言map實(shí)現(xiàn)順序讀取, 文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05

最新評(píng)論

永安市| 安乡县| 台湾省| 锡林浩特市| 衡阳市| 甘南县| 康保县| 林口县| 陆河县| 建水县| 莱芜市| 光山县| 富顺县| 密云县| 曲沃县| 玉山县| 洪湖市| 菏泽市| 玉门市| 桦甸市| 行唐县| 扎囊县| 花垣县| 宝清县| 苏州市| 邮箱| 汽车| 彭水| 绥中县| 朝阳区| 大丰市| 凤庆县| 岱山县| 邵东县| 军事| 蓬莱市| 凤阳县| 华容县| 乌什县| 南昌市| 民乐县|