GO中channel无缓冲和有缓存的区别

1,000 阅读1分钟

常规定义的channel都是默认不带缓冲的,如下代码所示

`package` `main`

`import` `(`

`    ``"fmt"`

`)`

`func` `main() {`

`    ``c := make(``chan` `int)`

`    ``c <- 1`

`    ``fmt.Println(<-c)`

`}`

运行上述代码,会产生一个错误

image.png

因为在默认不带缓冲的channel中,每一个发送者与接收者都会阻塞当前线程,只有当接受者与发送者都准备就绪了,channel才能正常使用,正确的使用如下所示

`package` `main`

`import` `(`

`    ``"fmt"`

`)`

`func` `main() {`

`    ``c := make(``chan` `int)`

`    ``//使用Goroutine使当前channel的发送不会阻塞线程`

`    ``go` `func``() {`

`        ``c <- 1`

`    ``}()`

`    ``fmt.Println(<-c)`

`}`

那么如何让程序同步执行,但是又不会阻塞线程呢?这是就可以用带缓冲的channel来进行实现,如下代码所示:

package main

import (

    ``"fmt"

)

`func` `main() {`

`    ``//创建一个缓冲大小为2的channel`

`    ``c := make(``chan` `int, 2)`

`    ``c <- 1`

`    ``c <- 2`

`    ``fmt.Println(<-c)`

`    ``fmt.Println(<-c)`

`}`

结果如下:

image.png

注意,这里的channel并不能无限的接收数据而不造成阻塞,能够接收的数据的个数取决于channel定义时,设定的缓冲的大小,只有在这个缓冲大小范围之内,channel的发送才不会造成阻塞

`package` `main`

`import` `(`

`    ``"fmt"`

`)`

`func` `main() {`

`    ``//创建一个缓冲大小为2的channel`

`    ``c := make(``chan` `int, 2)`

`    ``c <- 1`

`    ``c <- 2`

`    ``//这里channel的发送超出了缓冲的大小,所以会因为阻塞而导致程序死锁`

`    ``c <- 3`

`    ``fmt.Println(<-c)`

`    ``fmt.Println(<-c)`

`}`

以上程序依旧会因为channel的发送而导致程序阻塞,最后导致死锁

 

注意,虽然带缓冲的channel可以让发送在缓冲范围内不阻塞线程,但是channel的接收还是会照常被阻塞的。