为了账号安全,请及时绑定邮箱和手机立即绑定

使用 chan 和 sync.waitgroup 时的死锁

使用 chan 和 sync.waitgroup 时的死锁

Go
PIPIONE 2022-06-27 17:15:49
我目前正在学习并发。我编写了一个简单的测试程序来练习 goroutines。但是每当我执行此操作时,我都会收到一条错误消息,指出fatal error: all goroutines are asleep - deadlock!我不知道我做错了什么。有谁知道我如何使这项工作按预期进行。任何帮助都感激不尽import (    "fmt"    "sync"    "time")func slow(i int, cha chan int, wg *sync.WaitGroup) {    fmt.Println("HI", i)    time.Sleep(time.Second * 2)    cha <- i * 2    wg.Done()}func main() {    var wg sync.WaitGroup    values := make(chan int)    for i := 1; i < 12; i++ {        wg.Add(1)        go slow(i, values, &wg)    }    wg.Wait()    close(values)}编辑:当我尝试将通道设置为缓冲通道时,它可以工作。我不知道怎么
查看完整描述

1 回答

?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

您当前的程序无法运行,因为无缓冲通道没有消费者。此外,没有必要同时使用WaitGroup两者channel。


考虑下面的例子:


func slow(i int, cha chan int) {

  fmt.Println("HI", i)

  time.Sleep(time.Second * 2)

  cha <- i * 2

}


func main() {

  values := make(chan int)

  defer close(values)

  for i := 1; i < 12; i++ {

    go slow(i, values)

  }


  for i := 1; i < 12; i++ {

    fmt.Println(<-values)

  }

}

这样我们就可以有一个发送者 goroutine,并且可以在主函数中使用消息。


如果我们只是想确保所有的 goroutine 在 main 完成执行之前完成,我们可以像下面这样删除通道:


func slow(i int, wg *sync.WaitGroup) {

    fmt.Println("HI", i)

    time.Sleep(time.Second * 2)

    wg.Done()

}


func main() {

    var wg sync.WaitGroup

    for i := 1; i < 12; i++ {

        wg.Add(1)

        go slow(i, &wg)

    }

    wg.Wait()

}

使用缓冲通道有效,因为在缓冲区填满之前将消息推送到通道不再阻塞。


查看完整回答
反对 回复 2022-06-27
  • 1 回答
  • 0 关注
  • 138 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信