iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0
自我挑戰組

30 天學 Golang?Go 啦哪次不 Go系列 第 15

Day15# Goroutines

鐵人賽終於要過一半了,今天要來介紹 Go 的特色之一 -- Goroutines。
那麼話不多說,我們就進入正題吧 ─=≡Σ(((っ゚∀゚)っ

事前提要:必須先瞭解 thread 是什麼!

Goroutines

Goroutines 是由 Go runtime 管理的輕量 thread。

剛剛有提到,他能夠讓程式「同步」執行,但事實上 concurrency(併發)並不是真的同步,而是透過 thread 共享訊息,並且將資源分段處理不同的事情。

簡單的說,就是時間管理大師的概念,在一定的時間內把所有事情給處理完成。

起手式

如果對昨天的文章還有印象就會知道 Goroutines 的起手式,就是 go !

go f(x, y, z)

有了 go 做為起手式後,f 函式因此能跑在另一個 Goroutine 上。

咦,為什麼會說跑在「另一個」Goroutine 呢?
因為 Go 的程式裡會有一個主要的 main goroutine,而這東西就是我們每次都會用到的 main 函式,每當 main 函式執行完成後,就會強制把所有的 gorountine 給關閉掉。

不太了解為什麼嗎?讓我們來 try try see!

package main

import (
	"fmt"
)

func say(s string) {
	for i := 0; i < 5; i++ {
		fmt.Println(s)
	}
}

func main() {
	go say("world")
	go say("hello")
}

這時候應該會發現毫無反應,這是因為現在這個狀態總共開了 3 個 gorountine:mainsay("world")say("hello"),每個 goroutine 會乖乖排隊等待被執行,但 main 執行完後根本還沒輪到剩下的兩個,就強制關閉了所有的 goroutine。

要解決這個問題,就需要阻塞住 goroutine,這樣原本在運作的 A goroutine 忽然閒下來了,時間管理大師就能夠趕快再去 B goroutine 處理事情。

有三種方式能夠處理這問題:

  1. time.Sleep()
  2. sync.WaitGroup
  3. Channel
// time.Sleep()
package main

import (
	"fmt"
	"time"
)

func say(s string) {
	for i := 0; i < 5; i++ {
		fmt.Println(s)
	}
}

func main() {
	go say("world")
	go say("hello")
	time.Sleep(100 * time.Millisecond)
}
// sync.WaitGroup
package main

import (
	"fmt"
	"sync"
	"time"
)

func say(s string, wg *sync.WaitGroup) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}

	wg.Done()
}

func main() {
	wg := new(sync.WaitGroup)
	wg.Add(2)

	go say("world", wg)
	go say("hello", wg)

	wg.Wait()
}

結尾

至於 channel 怎麼使用,就交給明天的文章了
有任何問題歡迎與我告知 :)
本篇文章同步更新於我的部落格


上一篇
Day14# Thread
下一篇
Day16# Channel
系列文
30 天學 Golang?Go 啦哪次不 Go20

尚未有邦友留言

立即登入留言