go開攜程訪問mysql Go 協程的開啟和退出

2021-10-21 08:38:07 字數 1215 閱讀 5317

![illustration created for 「a journey with go」, made from the original go gopher, created by renee french.](

ℹ️本文基於 go 1.14。

在 go 中,協程就是乙個包含程式執行時的資訊的結構體,如棧,程式計數器,或者它當前的 os 執行緒。排程器還必須注意 goroutine 的開始和退出,這兩個階段需要謹慎管理。

## 開啟

開啟乙個協程的處理過程相當簡單。我們用乙個程式作為例子:

!(`main` 函式在列印資訊之前開啟了乙個協程。由於協程會有自己的執行時間,因此 go 通知執行時配置乙個新協程,意味著:

- 建立棧

- 收集當前程式計數器或呼叫方資料的資訊

- 更新協程內部資料,如 id 或 狀態

!(把協程放在佇列的前端,這樣它就會在當前協程執行之後第乙個執行。如果有工作竊取發生,它不是在當前執行緒就是在另乙個執行緒執行。

*我推薦你閱讀我的文章 [go: go 排程器中的工作竊取](來獲取更多資訊。*

在彙編指令中也可以看到協程的建立過程:

!(協程被建立並被加入到本地協程佇列後,它直接執行主函式的下乙個指令。

## 退出

協程結束時,為了不浪費 cpu 資源,go 必須排程另乙個協程。這也使協程可以在以後復用。

*在我的文章 [go: 協程怎麼復用?](中你可以找到更多資訊。*

然而,go 需要乙個能識別到協程結束的方法。這個方法是在協程建立時控制的。建立協程時,go 在將程式計數器設定為協**實呼叫的函式之前,將堆疊設定為名為 `goexit` 的函式。這個技巧可以使協程在結束時必須調 `goexit` 函式。下面的程式可以使我們理解得更形象:

!(根據輸出資訊進行堆疊追蹤:

```bash

/path/to/src/main.go:16

/usr/local/go/src/runtime/asm_amd64.s:1373

用彙編寫的 `asm_amd64` 檔案包含這個函式:

!(之後,go 切換到 `g0` 排程另乙個協程。

我們也可以呼叫 `runtime.goexit()` 來手動終止協程:

!(這個函式首先執行 defer 中的函式,然後會執行前面在協程退出時我們看到的那個函式。

本文由 gctt 原創編譯,go語言中文網 榮譽推出

文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽

go 協程等待

sync包提供了基本的同步基元,如互斥鎖 但是這裡不是討論執行緒通訊的問題 而執行緒通訊應使用channel 以前使用time.sleep 來保證執行緒執行完成,顯然執行緒執行所需要的時間不確定 sync裡面有乙個waitgroup,它是乙個結構體,可以用於等待執行緒執行 這樣不用去估算執行緒需要執...

Go 協程 通道

目錄 go 協程 go 通道 go 協程go 協程可以看作是輕量級執行緒。與執行緒相比,建立乙個go協程的成本很小。因此在go應用中,常常會看到有數以千計的go協程併發地執行 go 協程相比於執行緒的優勢 啟動乙個go協程 在呼叫函式和方法時,在前面加上關鍵字go,可以讓乙個新的go協程併發執行 p...

python 測開 協程

生成器原理 使用生成器實現多工 gevent實現非同步 協程核心思想 asyncio實現非同步 從python2到python3,協程經歷了翻天覆地的變化。協程的底層架構是在 pep 342 中定義,在 python2.5 實現的。實現思想 使用yield掛起生成器,使用send 方法啟用生成器。這...