我陷入了一种奇怪的情况,即对频道的写操作永远不会发生。
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
s := make(chan bool)
k := make(chan bool)
fmt.Println("start")
go func() {
fmt.Println("routine 1")
s <- true
}()
go func() {
fmt.Println("routine 2")
for {
select {
case <-s :
for i := 0; i < 3; i++ {
fmt.Println("before")
c <- i
fmt.Println("after")
}
case <- k :
fmt.Println("k ready")
break
}
}
}()
go func() {
fmt.Println("routine 3")
for {
select {
case x := <- c :
fmt.Println("x=", x)
k <- true
fmt.Println("k done")
}
}
}()
time.Sleep(1000 * time.Millisecond)
}
这是输出:
start
routine 1
routine 2
before
routine 3
x= 0
after
before
我想知道为什么写入通道k阻塞,但是从不打印日志语句fmt.Println("k ready")
。
以下是我的想法:
据我说它应该能够写入通道k然后goroutine的情况2应该执行并打印&#34; k ready&#34;
任何人都可以解释为什么写入频道被阻止? 作为一个修复,我知道我可以增加通道c的缓冲区大小,所有内容都会打印出来,但我不想修复它,而是想了解这种情况。
一个很好的blog来理解上述情况。
答案 0 :(得分:1)
你有一个僵局。
s
然后退出s
读取,并写入c
c
读取,并写入k
,这会阻止,因为没有任何内容正在从k
读取,因为goroutine 2在写入k
时被阻止上方。c
写入阻止,因为goroutine 3仍在尝试写入k
,因此不会从c
与您的说法相反,您的缓冲区大小不是1.您的缓冲区大小为零(即无缓冲通道),因此写入将阻塞,直到读取内容为止。这可能是你误解的根源。根据{{3}}:
可以使用内置函数
make
创建一个新的初始化通道值,该函数将通道类型和可选容量作为参数:make(chan int, 100)
容量(以元素数量)设置通道中缓冲区的大小。如果容量为零或不存在,则通道无缓冲,只有当发送方和接收方都准备就绪时,通信才会成功。否则,如果缓冲区未满(发送)或非空(接收),则通道被缓冲并且通信成功而不会阻塞。零通道从未准备好进行通信。