go - 将数据从不同的 goroutine 写入同一个通道可以正常工作,无需等待组
问题描述
在等待 wg.Wait() 后,使用带有 waitgroup 的多个 go 例程将数据写入同一通道时,出现异常说所有 go 例程都处于睡眠状态或 deedlock。
package main
import (
"fmt"
"runtime"
"sync"
)
var wg sync.WaitGroup
func CreateMultipleRoutines() {
ch := make(chan int)
for i := 0; i < 10; i++ { // creates 10 go routines and adds to waitgroup
wg.Add(1)
go func() {
for j := 0; j < 10; j++ {
ch <- j
}
wg.Done() // indication of go routine is done to main routine
}()
}
fmt.Println(runtime.NumGoroutine())
wg.Wait() //wait for all go routines to complete
close(ch) // closing channel after completion of wait fo go routines
for v := range ch { // range can be used since channel is closed
fmt.Println(v)
}
fmt.Println("About to exit program ...")
}
当试图在没有等待组的情况下实现这一点时,我可以通过循环将数据推送到通道的确切次数来从通道读取数据,但我无法确定范围,因为当我们关闭通道时会出现恐慌。这是示例代码
package main
import (
"fmt"
"runtime"
)
func main() {
ch := make(chan int)
for i := 0; i < 10; i++ { // creates 10 go routines and adds to waitgroup
go func(i int) {
for j := 0; j < 10; j++ {
ch <- j * i
}
}(i)
}
fmt.Println(runtime.NumGoroutine())
for v := 0; v < 100; v++ {
fmt.Println(<-ch)
}
fmt.Println("About to exit program ...")
}
我想了解为什么处于等待状态的等待组仍在等待,即使所有 go 例程都已发出信号 Done(),这反过来又使 go 例程的数量为零
解决方案
我认为您的原始代码存在一些问题。
- 您正在关闭通道,然后再读取它。
- 由于您的频道是 1“大小”,因此您没有获得使用 10 个 goroutine 的优势。所以一个 goroutine 每次产生一个结果。
我的解决方案是生成一个新的 goroutine 来监控 10 个 goroutine 是否完成了它的工作。在那里你将使用你的WaitGroup
.
然后代码将是:
package main
import (
"fmt"
"runtime"
"sync"
)
var wg sync.WaitGroup
func main() {
ch := make(chan int, 10)
for i := 0; i < 10; i++ { // creates 10 go routines and adds to waitgroup
wg.Add(1)
go func() {
for j := 0; j < 10; j++ {
ch <- j
}
wg.Done() // indication of go routine is done to main routine
}()
}
go func(){
wg.Wait()
close(ch)
}()
fmt.Println(runtime.NumGoroutine())
for v := range ch { // range can be used since channel is closed
fmt.Println(v)
}
fmt.Println("About to exit program ...")
}
推荐阅读
- hbase - HBase 2.0.0:区域链中的过渡洞中的区域
- php - Postgresql SQLSTATE[22021]: Character not in repertoire: Ö
- python - django分页过滤器-根据一行但出现错误
- linux - Move and copy text file in bash script
- c# - Progress bar does not update on separate form from VSTO addin
- android - App crashes with 'Unfortunately Age Calculator pro has stopped working' but there are no errors while compiling
- rest - NoTypeConversionAvailableException:骆驼休息 dsl
- c# - 无法在 UWP 项目中加载文件或程序集“PCLAppConfig”
- java - 优化 hashmap 中的搜索时间
- javascript - Laravel mix / webpack 不会在通过 babel() 编译的脚本上触发监视功能