与WaitGroup的Golang频道同步。关闭通道和等待组

问题描述 投票:0回答:2

我试图了解Goroutines中的同步。我这里有一个代码,可以在通道上写入从0到4的数字,完成后,我使用range从通道读取并打印值。

下面的代码在我使用wg.Wait()等待并在单独的Goroutine中关闭通道的地方很好用。

package main

import "fmt"
import "strconv"
import "sync"

func putvalue(i chan string, value string, wg *sync.WaitGroup) {
    i <- value
    defer wg.Done()
}

func main() {

    queue := make(chan string)
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go putvalue(queue, strconv.Itoa(i), &wg)
    }

    go func() {
        wg.Wait()
        close(queue)
    }()

    for elem := range queue {
        fmt.Println(elem)
    }

}

但是如果我使用完全相同的代码,但是等待并关闭主线程中的通道,则会导致死锁。下面的代码导致死锁。

package main

import "fmt"
import "strconv"
import "sync"

func putvalue(i chan string, value string, wg *sync.WaitGroup) {
    i <- value
    defer wg.Done()
}

func main() {

    queue := make(chan string)
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go putvalue(queue, strconv.Itoa(i), &wg)
    }

    wg.Wait()
    close(queue)

    for elem := range queue {
        fmt.Println(elem)
    }

}

据我所知,在第二种情况下,主线程执行停止并等待,但是与在单独的goroutine中执行它有何不同?请帮助我理解这一点。

go goroutine
2个回答
0
投票

在第一个程序中,主goroutine创建几个goroutine,其中每个goroutine在通道写入时开始等待。然后,主goroutine创建另一个等待wg.Wait()的goroutine。主goroutine继续,从通道中读取,这也使所有goroutine逐一启用,然后它们终止,释放goroutine,等待wg.Wait()

[在第二个程序中,您再次创建等待通道写入的goroutine,但是这次,主goroutine调用wg.Wait()。此时,您创建的所有goroutine都在等待通道变为可写状态,而主goroutine正在等待goroutine结束,这意味着死锁[]


0
投票

将每个goroutine视为一个单独的人(或gopher:https://blog.golang.org/gopher)可能会有所帮助。当您go f()时,您会得到一个新的人员/角色,并让他们执行该功能。因此,您有5个额外的地鼠正在运行:

© www.soinside.com 2019 - 2024. All rights reserved.