当前位置: > > > > 从不同的 go 例程将数据写入同一通道无需等待组即可正常工作
从不同的 go 例程将数据写入同一通道无需等待组即可正常工作
来源:stackoverflow
2024-04-29 09:15:38
0浏览
收藏
在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天米云就整理分享《从不同的 go 例程将数据写入同一通道无需等待组即可正常工作》,聊聊,希望可以帮助到正在努力赚钱的你。
问题内容
在等待 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 ...")
}
我想了解为什么处于等待状态的 waitgroup 仍在等待,即使所有 go 例程都发出 done() 信号,这又使 go 例程的数量为零
解决方案
默认情况下,chan 不保存任何项目,因此所有 go 例程在发送时都会被阻止,直到从中读取内容。他们从未真正到达 wg.done() 语句。
解决方案是在它自己的 go 例程中关闭通道。将 wg.wait() 和 close(ch) 行包装如下:
go func() {
wg.wait() //wait for all go routines to complete
close(ch) // closing channel after completion of wait fo go routines
}()
然后您可以范围覆盖通道,该通道仅在所有发送 go 例程完成后才会关闭(并且隐式地收到所有值)。
我认为您的原始代码有一些问题。
- 您将在读取频道之前关闭该频道。
- 由于您的通道的“大小”为 1,因此您无法获得使用 10 个 goroutine 的优势。因此,一个 goroutine 一次会产生一个结果。
我的解决方案是生成一个新的 goroutine 来监视 10 个 goroutine 是否完成其工作。在那里您将使用您的 waitgroup。
那么代码将是这样的:
557188879518
文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《从不同的 go 例程将数据写入同一通道无需等待组即可正常工作》文章吧,也可关注米云公众号了解相关技术文章。
