Golang Concurrency Note 0

Rain Wu
Golang 筆記
Published in
4 min readMar 1, 2019

我一直以來覺得自己 Coding 不好,很大一部分原因是因為我不熟非阻塞性編程,正好趁這次學習 Golang 擴充技能組的機會來好好鑽研一下。就算看了不少文章我還是覺得我沒有理解得很清楚,讀者請謹慎服用。

Parallelism? Concurrency?

Golang 在非阻塞性設計上採用的是 Concurrency,和以往使用其他語言時所採用的 Parallelism 有些不同。Parallelism 是個只能運行在多核機器上,讓每個 Core(CPU) 分攤負擔各自執行的方法,但執行時彼此互不干預。換句話說如果 CPU_0 跑到一半ㄎㄧㄤ掉了,沒有特地處理的話其他兩個 CPU 也救不了他後續沒處理完的東西。

Concurrency 就比較靈活一些,可以視為做完事情就去拿新事情來做的特性,也就是說一堆事情丟在那兒,沒有分哪些是誰要做的問題。如此一來就算其中一個人ㄎㄧㄤ掉,其他人也會認命地把剩下來的事情都做完。

如果說現在有一群學生在考期末,Parallelism 就像是每個學生各自寫自己的考卷,那麼理所當然的會有些考卷比較簡單所以早早寫完閒著,有些考卷比較難,轉筆轉到筆都飛出去了還是想不出來,可見其對於資源上的虛耗十分可觀。

如果使用 Concurrency 的話變成有一疊考卷在講桌上,大家要一起把所有考卷寫完,早點寫完的就會去幫寫不完的人,所有人一起解決掉所有問題(噢這樣說會不會有點共產),如此一來便比較不會出現有題目沒被寫完的問題。

Goroutine

在 Golang 中可以非常輕易地使用 go Func(arg) 來創造一個 Goroutine。

$ go build
$ .\main.exe
Hello
Hello

不過很快會發現,go say(“World”) 不過就是創建ㄧ個 Goroutine 而已,具體上他並沒有獲得執行的機會,而 say(“Hello”) 同樣是 Goroutine 並且執行完成。至於如何讓其他 Goroutine 獲得執行機會,可以修改一下代碼。

$ go build
$ .\main.exe
Hello
World
Hello

這次在 fmr.Println(s) 後多加上了 runtime.Gosched(),這方法的用處是讓當前執行的 Goroutine 讓出其執行權,讓 CPU 去執行另外一個 Goroutine,然後在不久的將來再回來執行自己。如此ㄧ來便會出現 say("Hello") 和 say("World") 兩個 Goroutine 互相交替執行的情況。

不過最後由於 say("Hello") 已經執行完成,因此不會再做後續讓出執行權的動作,使得第二的 for loop 的 World 並未被打印出來。

從 Concurrency 的角度來看,就是你搞出了一大堆 Goroutine,然後要 CPU 幫你解決掉它們。過程中,任何一個 Thread 在執行 Groutine 慘遭 block 時,Golang 會自動換上另一個 Goroutine 讓 Thread 執行,不會讓他有打混的機會。

不過具體上究竟蹦出了多少個 Thread 貌似無法得知,我們可以藉由設定 $GOMAXPROCS 來設定上限,避免他不受控的增加。

為了避免文章太長不易閱讀,這篇先寫到這裡打住。我對 Golang 的 Concurrercy 並不是十分理解,若上述內容有誤麻煩不吝指證。

--

--

Rain Wu
Golang 筆記

A software engineer specializing in distributed systems and cloud services, desire to realize various imaginations of future life through technology.