go - 如何在不出现死锁错误的情况下获得所有结果
问题描述
应该从切片中获取所有值,最终不会出现死锁。当我不使用 waitGroups 时,我没有收到死锁错误。 <-time.After(time.Second) 是我用来代替 waitGroup 的,这有帮助
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
c := make(chan int)
a := []int{1, 3, 10, 8, 15, 23}
wg.Add(len(a))
go func(i []int) {
for _, v := range i {
c <- v
}
}(a)
go Print(c)
wg.Wait()
}
func Print(c chan int) {
for v := range c {
fmt.Println(v)
}
wg.Done()
close(c)
}
解决方案
您对同步机制感到困惑。关键是要同步异步工作人员。不是他们将处理的元素数量。
您不会在写入结束后关闭通道,而是在读取应该结束后关闭。这是错误的。
您正在使生产者和消费者都异步。这有点奇怪。由于您已经在 main 中有一个线程,因此您可以利用它来不启动虚假例程。
修复后代码的一些变体
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main() {
c := make(chan int)
a := []int{1, 3, 10, 8, 15, 23}
wg.Add(1) // one async worker
go Print(c) // ensure the worker is started upfront
for _, v := range a {
c <- v // write the data
}
close(c) //then close
wg.Wait()
fmt.Println("done")
}
func Print(c chan int) {
for v := range c { // the loop will break because the channel is closed.
fmt.Println(v)
}
wg.Done()
}
您也可以在没有任何等待组的情况下构建它。
package main
import (
"fmt"
)
func main() {
c := make(chan int)
a := []int{1, 3, 10, 8, 15, 23}
go func() {
for _, v := range a {
c <- v // write the data
}
close(c) //then close
}()
for v := range c { // the loop will break because the channel is closed.
fmt.Println(v)
}
fmt.Println("done")
}
推荐阅读
- google-maps - 我们可以为 xamarin 形式的 android 和 xamarin 形式的 ios 使用单个 google map api 密钥吗?
- javascript - 用 d3 模拟音频波形
- google-api - 以编程方式批准驱动器文件访问请求
- reactjs - 仅当用户看到完整的视频组件时,如何以 react-native 播放视频?
- rest - sharepoint Addin 中的身份验证
- linux - 代理后面的 Docker 需要在启动时重新启动
- spring - 添加 javax.servlet-api 依赖项会引发 org.slf4j.impl.StaticLoggerBinder 无法加载但我不使用 sl4j 的异常,我使用的是 thymeleaf
- facebook-graph-api - Facebook API 查询子对象
- jenkins-pipeline - 如何在詹金斯的单个管道作业中触发多次运行?
- r - prcomp( .. ,retx=TRUE),我可以得到新的数据来训练吗?