无缓冲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中就读完了。这样的特性可以用于做并发单位之间的同步操作,如果在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的读写者必须同时完成发送和接收,读者只会在没有数据时阻塞,写者只会在没有可用容量时阻塞,这就有点像阻塞队列了。

posted @ 2020-08-25 15:05  joeyzzz  阅读(1393)  评论(0编辑  收藏  举报