【问题标题】:Getting Goroutine deadlock when using for loop to traverse through the channel使用for循环遍历通道时遇到Goroutine死锁
【发布时间】:2019-11-06 15:46:32
【问题描述】:

我正在尝试练习 goroutine 和通道,但我遇到了调用 gorouting 和传递通道的问题。 goroutine 会将数据推送到通道中,然后主线程将打印元素。

我用for循环来打印内容但是得到了。

fatal error: all goroutines are asleep - deadlock!

2
1
goroutine 1 [chan receive]:
main.main()
package main

import "fmt"


func smallThread(a int, c chan int) {
    c <- a
}

func main() {
    c := make(chan int)
    go smallThread(1, c)
    go smallThread(2, c)
    for {
        fmt.Println(<-c)
    }
}

编辑: 使用等待组:

func smallThread(a int, c chan int, w *sync.WaitGroup) {
    c <- a
    w.Done()
}

func main() {
    c := make(chan int)
    var w sync.WaitGroup
    w.Add(2)
    go smallThread(1, c, &w)
    go smallThread(2, c, &w)
    //w.Wait()
    for i := range c {
        fmt.Println(i)
    }
    w.Wait()
}

EDIT2:工作代码

func smallThread(a int, c chan int, w *sync.WaitGroup) {
    //defer w.Done()
    c <- a
    w.Done()
}

func main() {
    c := make(chan int)
    var w sync.WaitGroup
    w.Add(1)
    go smallThread(1, c, &w)
    w.Add(1)
    go smallThread(2, c, &w)
    go func(c chan int) {
        for i := range c {
            fmt.Println(i)
        }
    }(c)
    w.Wait()
}

【问题讨论】:

标签: go channel goroutine


【解决方案1】:

不确定您的问题是什么,但我会告诉您会发生什么。你的两个侧 goroutine 将它们的数字推送到通道并退出。然后主 goroutine(此时只剩下一个)将永远阻塞,等待另一个元素从通道中出来。

【讨论】:

  • 我该如何处理?
  • @JeYa:取决于你到底想要达到什么目标。
  • 我试图学习 goroutine 将数据推送到同一个通道和主线程或任何其他遍历它的线程
  • @JeYa:我想说,这个目标已经实现了。你成功地将数据从一个 goroutine 推送到一个通道,另一个 goroutine 读取它。
  • @JeYa:我在答案中解释了这一点。
【解决方案2】:

当 goroutines 完成后,关闭通道以指示不再添加任何值。当接收到所有值后,for 循环将中断。

c := make(chan int)
var w sync.WaitGroup
w.Add(2)
go smallThread(1, c, &w)
go smallThread(2, c, &w)
go func() {
    w.Wait()
    close(c)
}()

for i := range c {
    fmt.Println(i)
}

【讨论】:

  • 当我在goroutine之前添加w.Wait(),在go smallThread(2, c, &amp;w)之后,我得到死锁错误,我想等待主线程,除非所有smallThread都完成
  • @JeYa 因为通道是无缓冲的,所以 smallThread 协程直到主协程接收后才会完成。如果主 goroutine 在接收之前调用 w.Wait(),则 smallThread goroutines 在发送时阻塞。如果 goroutine 在发送时阻塞,那么它们永远不会调用 w.Done()。这是一个僵局。
猜你喜欢
  • 1970-01-01
  • 2016-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 1970-01-01
  • 1970-01-01
  • 2020-06-17
相关资源
最近更新 更多