理解 golang 通道:死锁
Understanding golang channels: deadlock
以下代码:
package main
import (
"fmt"
"strings"
)
var data = []string{
"The yellow fish swims slowly in the water",
"The brown dog barks loudly after a drink ...",
"The dark bird bird of prey lands on a small ...",
}
func main() {
histogram := make(map[string]int)
words := make(chan string)
for _, line := range data {
go func(l string) {
for _, w := range strings.Split(line, " ") {
words <- w
}
}(line)
}
defer close(words)
for w := range words {
histogram[w]++
}
fmt.Println(histogram)
}
以死锁结束:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/tmp/sandbox780076580/main.go:28 +0x1e0
我的理解是通道词会阻塞作者和 readers 以实现某种同步。我正在尝试为所有 goroutines(编写器)使用一个通道,并在 main 中使用一个 reader(使用 "range" 命令)。
我也尝试过缓冲通道 - 类似的失败。
我很难理解为什么这不起作用。有什么有助于理解的技巧吗?
谢谢。
如问题评论中所述,直到 main returns 才执行延迟。结果,超过 words
的范围将永远阻塞。
要解决此问题,应用程序必须在所有 goroutine 完成发送后关闭 words
。一种方法是使用 wait group。等待组为每个 goroutine 递增,当 goroutines 退出时递减。另一个 goroutine 在组上等待并关闭通道。
func main() {
histogram := make(map[string]int)
words := make(chan string)
var wg sync.WaitGroup
for _, line := range data {
wg.Add(1)
go func(l string) {
for _, w := range strings.Split(l, " ") {
words <- w
}
wg.Done()
}(line)
}
go func() {
wg.Wait()
close(words)
}()
for w := range words {
histogram[w]++
}
fmt.Println(histogram)
}
额外修复:问题中的 goroutine 引用了循环变量 iine
而不是参数 l
。常见问题 explains why this is a problem。
以下代码:
package main
import (
"fmt"
"strings"
)
var data = []string{
"The yellow fish swims slowly in the water",
"The brown dog barks loudly after a drink ...",
"The dark bird bird of prey lands on a small ...",
}
func main() {
histogram := make(map[string]int)
words := make(chan string)
for _, line := range data {
go func(l string) {
for _, w := range strings.Split(line, " ") {
words <- w
}
}(line)
}
defer close(words)
for w := range words {
histogram[w]++
}
fmt.Println(histogram)
}
以死锁结束:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/tmp/sandbox780076580/main.go:28 +0x1e0
我的理解是通道词会阻塞作者和 readers 以实现某种同步。我正在尝试为所有 goroutines(编写器)使用一个通道,并在 main 中使用一个 reader(使用 "range" 命令)。
我也尝试过缓冲通道 - 类似的失败。
我很难理解为什么这不起作用。有什么有助于理解的技巧吗?
谢谢。
如问题评论中所述,直到 main returns 才执行延迟。结果,超过 words
的范围将永远阻塞。
要解决此问题,应用程序必须在所有 goroutine 完成发送后关闭 words
。一种方法是使用 wait group。等待组为每个 goroutine 递增,当 goroutines 退出时递减。另一个 goroutine 在组上等待并关闭通道。
func main() {
histogram := make(map[string]int)
words := make(chan string)
var wg sync.WaitGroup
for _, line := range data {
wg.Add(1)
go func(l string) {
for _, w := range strings.Split(l, " ") {
words <- w
}
wg.Done()
}(line)
}
go func() {
wg.Wait()
close(words)
}()
for w := range words {
histogram[w]++
}
fmt.Println(histogram)
}
额外修复:问题中的 goroutine 引用了循环变量 iine
而不是参数 l
。常见问题 explains why this is a problem。