從零開發區塊鏈應用(十)--golang協程使用
一、什麼是併發
1.1 併發定義
為了更有意思的解釋這個概念,我借用知乎上的一個回答:你吃飯吃到一半,電話來了,你一直到吃完了以後才去接,這就說明你不支援併發也不支援並行。你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這說明你支援併發。你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支援並行。併發的關鍵是你有處理多個任務的能力,不一定要同時。並行的關鍵是你有同時處理多個任務的能力。對應到 CPU 上,如果是多核它就有同時執行的能力,即有並行的能力。對於 Go 語言,它自行安排了我們的程式碼合適併發合適並行。
1.2 併發的好處
二、什麼是協程
2.1 協程定義
協程是一種使用者態的輕量級執行緒,又稱微執行緒。
在go程式中,go語言在執行時會自動的建立和銷燬系統級的執行緒。系統級執行緒指的是作業系統提供的執行緒。
那麼對應的使用者級執行緒,指的是架設在系統級執行緒之上的,使用者級執行緒的建立、銷燬、排程、狀態變更,都需要靠我們的程式自己去實現和處理。
與執行緒相比,建立gotoutine的成本很小,他就是一段程式碼,一個函式入口
2.2 協程的優點
協程的建立和銷燬不需要通過作業系統去做,因此,是沒有執行緒切換的開銷,所以速度會很快,可以提高任務併發性
三、golang協程實踐
協程 類似於一個執行緒,但是由 Go 而不是作業系統預定。在 協程 中執行的程式碼可以與其他程式碼同時執行。我們來看一個
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("start")
go process()
time.Sleep(time.Millisecond * 10) // this is bad, don't do this!
fmt.Println("done")
}
func process() {
fmt.Println("processing")
}
這裡有一些有趣的事情, 但最重要的是我們如何開始一個 協程 。 我們只需使用 go 關鍵字,然後使用我們想要執行的函式。如果我們只想執行一部分程式碼, 如上所述, 我們可以使用匿名函式。需要注意的是,匿名函式不只是可以在 協程 中使用,其他地方也可以。
go func() {
fmt.Println("processing")
}()
協程 易於建立且開銷很小。最終多個 協程 將會在同一個底層的作業系統執行緒上執行。這通常也稱為 M:N 執行緒模型,因為我們有 M 個應用執行緒( 協程 )執行在 N 個作業系統執行緒上。結果就是,一個 協程 的開銷和系統執行緒比起來相對很低(幾 KB)。在現代的硬體上,有可能擁有數百萬個 協程 。
此外,這裡還隱藏了對映和排程的複雜性。我們只需要說 這段程式碼需要同時併發執行 然後讓 Go 自己去實現它。
如果我們回到我們的例子中,你將會注意到我們使用 Sleep 讓程式等了幾毫秒。這是因為主程序在退出前 協程 才會有機會去執行(主程序在退出前不會等待全部 協程 執行完畢)。要解決這個問題,我們需要協調我們的程式碼。
當你老了,回顧一生,就會發覺:什麼時候出國讀書,什麼時候決定做第一份職業、何時選定了物件而戀愛、什麼時候結婚,其實都是命運的鉅變。只是當時站在三岔路口,眼見風雲千檣,你作出選擇的那一日,在日記上,相當沉悶和平凡,當時還以為是生命中普通的一天。