sync.WaitGroup由值传递引起的死锁?

时间:2018-02-17 11:42:21

标签: go concurrency pass-by-reference pass-by-value

有2种方式来编写repro:

第一种方式,程序退出清洁。

func recurse(depth int, wg *sync.WaitGroup) {
    defer wg.Done()
    if depth == 0 {
        return
    }
    wg.Add(1)
    go recurse(depth - 1, wg)
}

func main() {
    wg := sync.WaitGroup{}
    wg.Add(1)
    go recurse(3, &wg)
    wg.Wait()
}

第二种方式,程序给出了#34;致命错误:所有goroutines都睡着了 - 死锁!"

func recurse(depth int, wg sync.WaitGroup) {
    defer wg.Done()
    if depth == 0 {
        return
    }
    wg.Add(1)
    go recurse(depth - 1, wg)
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go recurse(3, wg)
    wg.Wait()
}

有人会善意地解释第二种方式与第一种方式不同的错综复杂的方式,以便导致"死锁"?

1 个答案:

答案 0 :(得分:0)

引擎盖下的WaitGroup只是一个包含由互斥锁保护的计数器的结构。 Go为函数copy_by_value方式提供参数。因此,递归(深度,wg)函数在按值传递时仅接收计数器的副本。像这样:

counter := 5
func(counter){
    counter--
    fmt.Println(counter) //will print "4"
}(counter)
fmt.Println(counter) //will be "5" again