1. 程式人生 > 實用技巧 >無緩衝channel與容量為1的channel的區別

無緩衝channel與容量為1的channel的區別

有緩衝和無緩衝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中就讀完了。這樣的特性可以用於做併發單位之間的同步操作,有點像一個條件變數。所以,如果在一個協程裡寫這樣的程式碼,一定會死鎖:

func main() {
	ch := make(chan int)
	ch <- 1
        <- ch
}

無緩衝的channel的讀寫者必須同時完成傳送和接收,而不能序列,顯然單協程無法滿足。所以這裡造成了迴圈等待,會死鎖。

緩衝為1的channel

我們依然繼續上面提到的簡單場景:A向channel寫入一個int,B從channel讀走一個int。還是一樣的程式碼:

c2 <- 1   // A
<- c2     // B

這裡和無緩衝通道不同的地方在於:有緩衝的通道並不強制channel的讀寫者必須必須同時完成傳送和接收,讀者只會在沒有資料時阻塞,寫者只會在沒有可用容量時阻塞,這就有點像阻塞隊列了。