這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
目錄
-
- 並發
- goroutine
- Channel
- 概述
- 建立 Channel
- 單向 Channel
- 使用沒有緩衝的 Channel
- 使用有緩衝的 Channel
- 多線程同步
- 開啟多線程
- 使用 Channel 同步
- 使用 WaitGroup 同步
- Select
摘要
goroutine,Channel 作用,單向與雙向 channel,生產者與消費者模式,緩衝與無緩衝 channel,同步與非同步,WaitGroup,Select, timeout
並發
goroutine
使用 goroutine
文法為 go 方法名()
import "time"func test01() { fmt.Println("test01...")}go test01() //test01...time.Sleep(1 * time.Second)
以上如果不調用 Sleep() 方法則 main() 方法結束後程式就結束了,其它線程無法得到執行的機會
Channel
概述
Channel 是參考型別
Channel 可以用於阻塞線程
- 可以設定緩衝,緩衝預設為
0
- 緩衝沒有填滿之前不會阻塞
Channle 的主要作用是訊息傳遞和同步
建立 Channel
文法
- 建立 Channel
make(chan type, cacheSize)
- 關閉 Channel
close(ch)
- 向 Channel 中存入資料
ch<-data
- 從 Channel 中讀取資料
<-ch
單向 Channel
預設建立的 Channel 為雙向的,也可以建立唯讀或唯寫的單向 Channel。
單向 Channel 一般用於訊息傳遞。
唯寫 Channel
var ch1 chan<- int
唯讀 Channel
var ch2 <-chan int
生產者,消費者樣本
func producer(queue chan<- int) { for i := 0; i < 10; i++ { queue <- i fmt.Println("send:", i) } close(queue)}func consumer(queue <-chan int) { for i := 0; i < 10; i++ { v := <-queue fmt.Println("receive:", v) }}queue := make(chan int, 1)go producer(queue)go consumer(queue)time.Sleep(1 * time.Second)
使用沒有緩衝的 Channel
沒有緩衝的 Channel 又稱為同步 Channel,主要用於同步操作。
接收方會一直阻塞直到有資料到來。如果 channel 是無緩衝的,發送方會一直阻塞直到接收方將資料取出。
func test02(ch chan bool) { fmt.Println("test02...") fmt.Println("waiting...") ch <- true close(ch)}ch := make(chan bool)go test02(ch)//以下代碼中 ch 阻塞線程等待輸入,直到 test02()中 true被輸入到 channel 中<-ch //test02... waiting...ch = make(chan bool)go test02(ch)for v := range ch { fmt.Println(v)}<-ch //test02...waiting...true
使用有緩衝的 Channel
接收方會一直阻塞直到有資料到來。如果 channel 帶有緩衝區,發送方會一直阻塞直到資料被拷貝到緩衝區;如果緩衝區已滿,則發送方只能在接收方取走資料後才能從阻塞狀態恢複。
func test05(ch chan bool) { fmt.Println("test05...") fmt.Println("waiting test05...") ch <- true fmt.Println("waiting 01...") fmt.Println("waiting 02...") fmt.Println("waiting 03...") close(ch)}ch = make(chan bool, 10)go test05(ch)d := <-chfmt.Println("d", d) //test05... waiting test05... waiting01 waiting02 waiting03 true
多線程同步
開啟多線程
開啟多線程使用如下代碼
import "runtime"runtime.GOMAXPROCS(runtime.NumCPU())
使用 Channel 同步
func test03(ch chan bool, index int) { a := 1 for i := 0; i < 1000; i++ { a += i } fmt.Println("test03", index, a) ch <- true}ch = make(chan bool, 10)for i := 0; i < 10; i++ { go test03(ch, i) //向 Channel 寫10次}for i := 0; i < 10; i++ { <-ch //從 Channel 讀10次}
使用 WaitGroup 同步
func test04(wg *sync.WaitGroup, index int) { a := 1 for i := 0; i < 1000; i++ { a += i } fmt.Println("test04", index, a) wg.Done()}wg := sync.WaitGroup{}wg.Add(10)for i := 0; i < 10; i++ { go test04(&wg, i)}wg.Wait()
Select
概述
- 可按隨機順序同時處理多個
channel
- 可用
空 channel 阻塞 main 線程
- 可設定
timout 時間
使用 Select
定義三個 Channel
c1, c2 := make(chan int), make(chan string) //進行資料轉送o := make(chan bool) //進行阻塞
定義 goroutine
go func() { for { select { case v, ok := <-c1: if !ok { o <- true break } fmt.Println("c1", v) case v, ok := <-c2: if !ok { o <- true break } fmt.Println("c2", v) } } }()c1 <- 1c2 <- "hi"c1 <- 2c2 <- "hello"close(c1)close(c2)<-o//c1 1 -> c2 hi -> c1 2 -> c2 hello
設定 Timeout
select {case <-time.After(2 * time.Millisecond): fmt.Println("timeout")}