今天不延用 BasicGo 的標題,並非 Concurrency 很困難,而是他在 golnag 中可以被輕易實踐,反而容易造成初學者的一些困擾與誤解,建議首次使用的朋友們慎重看待他。
In computer science, concurrency is the ability of different parts or units of a program, algorithm, or problem to be executed out-of-order or in partial order, without affecting the final outcome
以下圖為例,將兩個任務個別拆分成較小的子任務,並且同時丟到 thread 中執行,由於是同時丟入 thread 中,所以順序上無法保證哪一個任務先被處理完成。
我們用一個簡單的範例,來觀察併發的情況有什麼不同。
package main
import (
"fmt"
"time"
)
func main() {
serialize()
fmt.Println("-----")
concurrency()
time.Sleep(time.Second)
}
func serialize() {
for i := 0; i < 5; i++ {
fmt.Println(i)
time.Sleep(500 * time.Millisecond) //為方便觀察睡一下
}
}
func concurrency() {
for i := 0; i < 5; i++ {
//golang 併發的關鍵保留字 "go"
go func(i int) {
fmt.Println(i)
time.Sleep(500 * time.Millisecond) //由於是同時進行,0~4將同時 sleep
}(i)
}
}
output
0
1
2
3
4
-----
4
1
0
3
2
由上面的範例可以觀察到,雖然可以將任務同時發出,但卻無法保證順序。那我們是否只能將相同且互不相干任務併發呢?答案是我們當然可以透夠一些方法,來進行同步也就是阻塞的動作,來達成將多個任務,依照合理的需求進行排列組合。
明日我們將會先介紹,沒處理好 goroutine 所產生的 data race 問題,並用三種阻塞手段控制我們的 goroutine。畢竟我們如果沒有滿足 ”without affecting the final outcome“ ,怎麼能算是 go consistently 呢?先讓我們從最小的地方也就是 memory consistency 做起吧!