为什么我的 golang goroutine 代码会死锁

时间:2021-06-08 13:27:31

标签: go goroutine

我尝试用 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 只是不让我提交问题......所以我只需要添加一些文本......

2 个答案:

答案 0 :(得分:4)

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

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

但它们在 chan1(或 chan2)上阻塞,因为它是一个无缓冲通道。

chan1 := make(chan string)

尝试将 chan1chan2 更改为缓冲通道:

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

答案 1 :(得分:1)

此代码在主协程中的 wg.Wait() 上阻塞,并在工作进程中写入 c1。为避免这种情况 - 在 c1 之前从 c2wg.Wait() 读取,从而解除对 worker 的阻塞,并且它们不会在写入缓冲的 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)
}