同步。WaitGroup 死锁是由 pass by value 引起的?

sync.WaitGroup deadlock caused by pass by value?

提问人:igbgotiz 提问时间:2/17/2018 更新时间:2/17/2018 访问量:839

问:

有 2 种方法可以编写重现:

第一种方式,程序干净地退出。

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()
}

第二种方式,程序给出“致命错误:所有 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()
}

谁能解释一下第二种方式与第一种方式的复杂方式不同,从而导致“僵局”?

Go 并发 引用传递值

评论

0赞 JimB 2/17/2018
请注意,此编程错误是由 vet 工具捕获的。

答:

2赞 Uvelichitel 2/17/2018 #1

后台的 WaitGroup 只是一个结构,其中包含一个由互斥锁保护的计数器。copy_by_value方式为函数提供参数。因此,recur( depth, wg) 函数在按值传递时仅接收计数器的副本。喜欢这个:

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