我不明白为什么这适用于无缓冲通道,或者为什么需要等待组

在这段代码中,我调用了一个函数来计算字符串中字母的数量,并返回一个符文图。为了利用并发性,我使用 goroutines 调用该函数:


func ConcurrentFrequency(l []string) FreqMap {

    var wg sync.WaitGroup

    wg.Add(len(l))

    m := FreqMap{}


    // Using unbuffered channel

    // ch := make(chan FreqMap, len(l))

    ch := make(chan FreqMap)


    for _, s := range l {

        go func(s string, ch chan<- FreqMap) {

            defer wg.Done()

            ch <- Frequency(s)

        }(s, ch)

    }

    go func() {

        wg.Wait()

        close(ch)

    }()


    for cm := range ch {

        for r, n := range cm {

            m[r] += n

        }

    }


    return m

}

如果我在不使用等待组和关闭通道的 goroutine 的情况下尝试此代码:


    go func() {

        wg.Wait()

        close(ch)

    }()

,然后我陷入僵局。


我不明白的是,为什么我能够遍历无缓冲通道,并从中读取多个地图。


这是完整的程序: https ://go.dev/play/p/zUwr_HvTT5w


并发方法仅比顺序方法快:

goos: linux

goarch: amd64

pkg: letter

cpu: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz

BenchmarkSequentialFrequency

BenchmarkSequentialFrequency-2              2820            367128 ns/op           17571 B/op         13 allocs/op

BenchmarkConcurrentFrequency

BenchmarkConcurrentFrequency-2              4237            282632 ns/op           12682 B/op         72 allocs/op

PASS

ok      letter  3.320s


幕布斯7119047
浏览 50回答 1
1回答

jeck猫

道上的 for-range 循环会一直持续到通道关闭为止。如果删除最终关闭通道的 goroutine,则 for 循环永远不会终止。一旦所有的 goroutines 发送值都完成了,就只剩下一个 goroutine 并且它被永远阻塞,等待通道关闭。缓冲通道与此问题无关。他们只帮助处理被阻止的发件人,但这里的问题是被阻止的接收者。
打开App,查看更多内容
随时随地看视频慕课网APP