gorouines是否忽略通道的缓冲区大小

zon*_*gyi 2 channel go capacity goroutine

环境:OS X 10.8,Go 1.0.2

我创建一个缓冲区大小为2的通道,然后如果我写通道三次,它将抛出错误:

扔:所有的goroutines都睡着了 - 僵局!

当然,这是正确的.

但是如果我在goroutines中写入通道四次或更多次,它工作正常,为什么?频道的容量是2,为什么goroutines会忽略或忽略容量设置?我评论了读取通道代码,因此没有人会读取通道并保存容量.我也用time.Sleep等待所有goroutines完成他们的工作.

请查看以下代码:package main

//import "fmt"

func main() {
    c := make(chan int, 2)
    /*c <- 1
    c <- 2
    c <- 3*/
    for i:=0; i<4; i++ {
        go func(i int) {
            c <- i
            c <- 9
            c <- 9
            c <- 9
        }(i)
    }
    time.Sleep(2000 * time.Millisecond)

    /*for i:=0; i<4*2; i++ {
        fmt.Println(<-c)
    }*/
}
Run Code Online (Sandbox Code Playgroud)

有人会请点击一下吗?多谢你们.

val*_*val 8

当通道被缓冲时,这意味着它将不会阻塞,直到缓冲区已满.一旦缓冲区已满,发送goroutine将在尝试向通道添加内容时阻止.

这意味着这将阻止:

c := make(chan int)
c <- 1          // Block here, this is unbuffered !
println(<-c)
Run Code Online (Sandbox Code Playgroud)

将阻止:

c := make(chan int, 2)
c <- 1
c <- 2
c <- 3           // Block here, buffer is full !
println(<-c)
Run Code Online (Sandbox Code Playgroud)

但是,够程和渠道的恰恰是同时运行的东西,所以这将工作:

c := make(chan int)
go func() { c <- 1; }() // This will block in the spawned goroutine until...
println(<-c)            // ... this line is reached in the main goroutine
Run Code Online (Sandbox Code Playgroud)

同样地:

c := make(chan int, 2)
go func() {  // `go ...` spawns a goroutine
    c <- 1   // Buffer is not full, no block
    c <- 2   // Buffer is not full, no block
    c <- 3   // Buffer is full, spawned goroutine is blocking until...
}()
println(<-c) // ... this line is reached in the main goroutine
Run Code Online (Sandbox Code Playgroud)

在您的示例中,您生成了四个不同的goroutine,它们都将四个数字写入同一个缓冲通道.由于缓冲区为2 <16,它们将最终阻塞

但问题的关键在于Go政策只是等待主要的goroutine:

程序执行从初始化主包然后调用main函数开始.当函数main返回时,程序退出.它不等待其他(非主要)goroutines完成.

这意味着在您的第一个示例中, goroutine在到达线时会阻塞c <- 3.由于没有其他goroutine能够做任何可能解除阻塞的东西,运行时检测到程序已死锁并报告错误.

然而,在你的第二个例子中,产生的 goroutines阻塞,而main继续静止直到它到达执行结束,此时所有(被阻止的)产生的goroutine被静默杀死,并且没有报告错误.