繁体   English   中英

golang频道死锁问题,我应该关闭频道吗

[英]golang channel deadlock problems, should I close the channel

package main

import (
    "fmt"
    "sync"
)

func main(){
    ch1 := make(chan int,100)
    ct := 0
    var wg sync.WaitGroup

    wg.Add(1)
    go func(){
        //defer close(ch1)
        for i:= 0; i < 10;i ++{
            ch1 <- i
        }
    }()

    go func(){
        defer wg.Done()
        for x := range ch1{
            fmt.Println(x)
        }
    }()
    wg.Wait()

    fmt.Println("numbers:",ct)
}

为什么这段代码会返回fatal error: all goroutines are asleep - deadlock! 我发现如果我关闭频道就不会出现死锁,但我不知道为什么会这样。 将所有项目输入频道后是否必须关闭频道?

仅当/当通道关闭时,通道上for range才会终止。 如果你不关闭通道并且不发送更多的值, for range语句将永远阻塞, wg.Wait()main goroutine 也会阻塞。

一旦发送所有值,“发送方”方应关闭通道,向“接收方”方发出信号,表示通道上不会再有任何值。

所以是的,你应该关闭频道:

go func() {
    defer close(ch1)
    for i := 0; i < 10; i++ {
        ch1 <- i
    }
}()

除非您关闭通道,否则从通道读取的 for 循环将继续读取。 这就是死锁的原因,因为从通道读取的 goroutine 是唯一活动的 goroutine,没有其他 goroutine 可以写入。 当您关闭时,for 循环终止。

  1. 范围未关闭的 ch1 将导致阻塞;
  2. 即使关闭 ch1,仍然可以从 ch1 接收数据;
  3. 可以说,close(ch1)会向ch1发送一个特殊的消息,可以用来通知ch1的接收者不会再收到数据了。 所以即使ch1里有数据,也可以close(),而不会导致接收方收不到剩余的数据。
  4. 通道不需要通过close来释放资源。 只要没有 goroutine 持有通道,相关资源就会自动释放。 取消注释 defer close(ch1) 将解决这个问题。 这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM