有緩沖和無緩沖channel的聲明
下面簡要說明它們之間的區別,先聲明兩個channel分別有緩沖1和無緩沖:
c1 := make(chan int) // 無緩沖
c2 := make(chan int, 1) // 有緩沖
無緩沖的channel
下面討論一個簡單的場景:A向channel寫入一個int,B從channel讀走一個int,
對於c1,可以假設A和B是兩個goroutine,是兩個並發單位。代碼如下:
c1 <- 1 // A
<- c1 // B
重點來了:這里的A或B,無論誰先執行,誰都會阻塞以等待另一個goroutine執行,也就是說往里寫得等來讀的,從里讀得等來寫的。最重要的是,A和B對c1的讀寫是同步的,直觀的理解是A和B對c1的讀寫是同時發生的,當A對c1寫完了,則B從c1中就讀完了。這樣的特性可以用於做並發單位之間的同步操作,如果在A和B中對同一個無緩沖通道進行了讀寫,那么A和B一定會在讀寫的地方進行同步,誰先到誰阻塞等待另外一個。
綜上,如果在一個協程里寫這樣的代碼,一定會死鎖:
func main() {
ch := make(chan int)
ch <- 1
<- ch
}
無緩沖的channel的讀寫者必須同時完成發送和接收,而不能串行,顯然單協程無法滿足。所以這里造成了循環等待,會死鎖。
緩沖為1的channel
我們依然繼續上面提到的簡單場景:A向channel寫入一個int,B從channel讀走一個int。還是一樣的代碼:
c2 <- 1 // A
<- c2 // B
這里和無緩沖通道不同的地方在於:有緩沖的通道並不強制channel的讀寫者必須同時完成發送和接收,讀者只會在沒有數據時阻塞,寫者只會在沒有可用容量時阻塞,這就有點像阻塞隊列了。