【发布时间】:2017-06-06 12:48:06
【问题描述】:
我陷入了一种奇怪的情况,对通道的写操作永远不会发生。
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") 从未打印出来。
这是我的想法:
- goroutine 1 将 true 写入通道 s
- 执行例程 2 将 0 写入 通道 c 并等待,因为缓冲区大小为 0,它将无法 除非有人阅读频道 c,否则向其写入 '1'
- goroutine 3 进入图片,读取通道 c(现在 goroutine 2 可以在执行例程 2 恢复后写入 c)打印 x 的值。 现在它应该可以写入通道 K 了,但这并没有发生
据我所知,它应该能够写入通道 k,然后 goroutine 的案例 2 应该执行并打印“k ready”
谁能解释我为什么写信给被屏蔽的频道? 作为修复,我知道我可以增加通道 c 的缓冲区大小,所有内容都会被打印出来,但我对修复这个问题不感兴趣,而是想了解这种情况。
一个很好的blog来理解上面的案例。
【问题讨论】:
-
以上代码的链接是here
标签: go deadlock channel goroutine