Go 緩衝 channel 和 非緩衝 channel 的區別
阿新 • • 發佈:2019-01-02
在看本篇文章前我們需要了解阻塞的概念
- 在執行過程中暫停,以等待某個條件的觸發 ,我們就稱之為阻塞
在Go中我們make一個channel有兩種方式,分別是有緩衝的和沒緩衝的
- 緩衝
channel
即buffer channel
建立方式為make(chan TYPE,SIZE)
- 如
make(chan int,3)
就是建立一個int
型別,緩衝大小為3
的channel
- 如
- 非緩衝
channel
即unbuffer channel
建立方式為make(chan TYPE)
- 如
make(chan int)
int
型別的非緩衝channel
- 如
- 非緩衝
channel
和 緩衝channel
的區別- 非緩衝
channel
,channel
傳送和接收動作是同時發生的 - 例如
ch := make(chan int)
,如果沒goroutine
讀取接收者<-ch
,那麼傳送者ch<-
就會一直阻塞 - 緩衝
channel
類似一個佇列,只有佇列滿了才可能傳送阻塞
- 非緩衝
-
程式碼演示
-
非緩衝
channel
package main
import (
"fmt"
"time"
)
func loop(ch chan int) {
for {
select {
case i := <-ch:
fmt.Println("this value of unbuffer channel", i)
}
}
}
func main() {
ch := make(chan int)
ch <- 1
go loop(ch)
time.Sleep(1 * time.Millisecond)
}
- 這裡會報錯
fatal error: all goroutines are asleep - deadlock!
就是因為ch<-1
- 但如果我們把
ch <- 1
放到go loop(ch)
下面,程式就會正常執行
- 緩衝
channel
的阻塞只會發生在channel
的緩衝使用完的情況下
package main
import (
"fmt"
"time"
)
func loop(ch chan int) {
for {
select {
case i := <-ch:
fmt.Println("this value of unbuffer channel", i)
}
}
}
func main() {
ch := make(chan int,3)
ch <- 1
ch <- 2
ch <- 3
ch <- 4
go loop(ch)
time.Sleep(1 * time.Millisecond)
}
- 這裡也會報
fatal error: all goroutines are asleep - deadlock!
,這是因為channel
的大小為3
,而我們要往裡面塞4
個數據,所以就會阻塞住 - 解決的辦法有兩個
- 把
channel
開大一點,這是最簡單的方法,也是最暴力的 - 把
channel
的資訊傳送者ch <- 1
這些程式碼移動到go loop(ch)
下面 ,讓channel
實時消費就不會導致阻塞了
- 把