我不明白为什么这适用于无缓冲通道,或者为什么需要等待组
I don't understand why this works with an unbuffered channel, or why a wait group is needed
在这段代码中,我调用了一个计算字符串中字母数量的函数,return 一个符文映射。为了利用并发性,我使用 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
A for-range loop over a channel continues until the channel is closed.
如果删除最终关闭通道的 goroutine,for 循环永远不会终止。一旦所有的 goroutines 发送值都完成了,只剩下一个 goroutine 并且它永远被阻塞,等待通道关闭。
缓冲通道与此问题无关。他们只帮助处理被阻止的发件人,但这里的问题是被阻止的接收者。
在这段代码中,我调用了一个计算字符串中字母数量的函数,return 一个符文映射。为了利用并发性,我使用 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
A for-range loop over a channel continues until the channel is closed.
如果删除最终关闭通道的 goroutine,for 循环永远不会终止。一旦所有的 goroutines 发送值都完成了,只剩下一个 goroutine 并且它永远被阻塞,等待通道关闭。
缓冲通道与此问题无关。他们只帮助处理被阻止的发件人,但这里的问题是被阻止的接收者。