【问题标题】:why my golang goroutine code get deadlocked为什么我的 golang goroutine 代码会死锁
【发布时间】:2021-06-08 13:27:31
【问题描述】:

我尝试用 channel 写一些 goroutine,但是死锁了,为什么? 我是不是对 WaitGroup 做错了,所以很困惑...

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {
    chan1 := make(chan string)
    chan2 := make(chan string)
    chan3 := make(chan string, 2)
    wg.Add(1)
    go makeChanStr("yeye", chan1, chan3)
    wg.Add(1)
    go makeChanStr("okok", chan2, chan3)
    wg.Wait()
    close(chan3)
    println(<-chan1)
    println(<-chan2)
    for chs := range chan3 {
         println(chs)
    }
}

func makeChanStr(s string, c1 chan string, c2 chan string) {
    defer wg.Done()

    c1 <- "get " + s
    c2 <- "same value"
    fmt.Printf("execute ok %s", s)
}

Stackoverflow 只是不让我提交问题......所以我只需要添加一些文本......

【问题讨论】:

  • 你正在等待 goroutines 返回之前从通道接收。如果您取消阻止,您将在关闭的频道上恐慌发送。也许从一个并发的工作示例开始,然后根据您的需要对其进行修改。
  • 你在等待 goroutines 完成后再从通道中读取,但是 goroutines 在它们可以发送之前无法完成,并且在某些东西准备好接收之前它们不能发送。 goroutines 互相等待,这是一个死锁。

标签: go goroutine


【解决方案1】:

wg.Wait() 上的主块,等待这两个 go 例程完成(因为 wg.Add(1) 和 wg.Done())

go makeChanStr("yeye", chan1, chan3)
go makeChanStr("okok", chan2, chan3)

但他们阻止 chan1(或 chan2),因为它是一个非缓冲通道。

chan1 := make(chan string)

尝试将chan1 和chan2 更改为缓冲通道:

chan1 := make(chan string,1)
chan2 := make(chan string,1)

【讨论】:

    【解决方案2】:

    这段代码阻塞在主 goroutine 中的 wg.Wait() 上,并写入 worker 中的 c1。为了避免这种情况 - 在wg.Wait() 之前从c1 和c2 读取,因此解除阻塞工作人员并且他们不会阻塞写入缓冲的c3。结果wg.Done() 将被调用,wg.Wait() 也不会阻塞 main goroutine。

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    var wg sync.WaitGroup
    
    func main() {
        chan1 := make(chan string)
        chan2 := make(chan string)
        chan3 := make(chan string, 2)
        wg.Add(1)
        go makeChanStr("yeye", chan1, chan3)
        wg.Add(1)
        go makeChanStr("okok", chan2, chan3)
        println(<-chan1)
        println(<-chan2)
        wg.Wait()
        close(chan3)
        for chs := range chan3 {
             println(chs)
        }
    }
    
    func makeChanStr(s string, c1 chan string, c2 chan string) {
        defer wg.Done()
    
        c1 <- "get " + s
        c2 <- "same value"
        fmt.Printf("execute %s\n", s)
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-10
      • 1970-01-01
      • 2021-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-04
      • 2017-07-31
      • 2012-08-27
      相关资源
      最近更新 更多