channel死锁问题
来源:11-2 使用Channel等待任务结束
KimZing
2018-03-25
func channelPrint(id int, ch chan int, done chan bool) {
for {
fmt.Printf("worker %d recevied %c \n", id, <- ch)
//done <- true
go func() {done <- true}()
}
}
func channelArrayDemo() {
var channels [10]chan int
var dones [10]chan bool
for i, _ := range channels {
channels[i] = make(chan int)
dones[i] = make(chan bool)
go channelPrint(i, channels[i], dones[i])
}
for i, _ := range channels {
channels[i] <- 'a' + i
}
for i, _ := range channels {
channels[i] <- 'A' + i
}
//for i,_ := range dones {
// <- dones[i]
// <- dones[i]
//}
//wait for all goroutine
time.Sleep(5 * time.Second)
}老师,您好,关于代码中`done <- true`改为`go func() {done <- true}()`就能避免死锁不是完全理解,虽然新开了协程来向done中放入bool,但是如果下面的两个`<-dones[i]`还没有执行到的话就应该报错。为了实验,我注释掉了`<-dones[i]`之后,仍然正常。想了很久没想通,麻烦老师解惑下,谢谢
一开始猜测会不会和闭包的机制类似,写了一个简短的Demo,运行同样通过,打印了in这个channel的指针,发现是同一个,还是没有搞明白。
import (
"fmt"
"time"
)
func send(in chan int) {
fmt.Println(in)//一样的
in <- 10
}
func main() {
in := make(chan int)
go send(in)
go send(in)
time.Sleep(time.Second)
fmt.Println(<-in)
fmt.Println(<-in)
}写回答
3回答
-
Gundy
2018-04-08
http://tb.am/cpbtj 阿里云ECS,1 核 2 G 1 M 带宽 40 G SSD 硬盘,3 年 279 元,需要的抓紧上车啦
00 -
sd1700092
2018-04-08
楼主,其实我还是没明白,为什么`done <- true`改为`go func() {done <- true}()`就能避免死锁?
看了你自己给自己的回答,我表示仍然不解……
采用并行的方式往同一个channel里发数据,就能避免死锁。而采用串行的方式往同一个channel里发数据,就能发生死锁。
这个道理是何在呢?
00 -
KimZing
提问者
2018-03-26
终于想明白了,写了下面两个demo
第一个:
func recieve(ch chan int) { time.Sleep(time.Second) fmt.Printf("接收到:%d \n" , <-ch) fmt.Printf("接收到:%d \n" , <-ch) for { fmt.Print() } } func main() { ch := make(chan int) go recieve(ch) ch <- 1 fmt.Println("1发送完毕") ch <- 2 fmt.Println("2发送完毕") ch <- 3 fmt.Println("3发送完毕") } 输出: 1发送完毕 接收到:1 接收到:2 2发送完毕 没有打印『3发送完毕』,说明在ch <- 3这一行阻塞了。 然后写了另外一个demo var ch = make(chan int) func send(ch chan int) { ch <- 12 fmt.Println("i am waiting for println 12") ch <- 13 fmt.Println("i am waiting for println 13") } func main() { go send(ch) time.Sleep(5 * time.Second) } 程序没有任何输出。程序中没有接收者,在"ch <- 12"这一行就已经阻塞了, 并没有执行到"ch <- 13"。00
相似问题