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
相似问题