在没有等待组的情况下,从不同的go例程将数据写入同一个chanel中工作正常
在等待wg之后,使用waitgroup的多个go例程将数据写入同一通道时。Wait()出现异常,表示所有go例程都处于休眠或解除锁定状态在没有等待组的情况下,从不同的go例程将数据写入同一个chanel中工作正常,go,Go,在等待wg之后,使用waitgroup的多个go例程将数据写入同一通道时。Wait()出现异常,表示所有go例程都处于休眠或解除锁定状态 package main import ( "fmt" "runtime" "sync" ) var wg sync.WaitGroup func CreateMultipleRoutines() { ch := make(chan int) for i := 0; i < 10; i++ { // cre
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 ...")
}
主程序包
进口(
“fmt”
“运行时”
“同步”
)
var wg sync.WaitGroup
func createmultiperoutines()函数{
ch:=制造(成交量)
对于i:=0;i<10;i++{//创建10个go例程并添加到waitgroup
工作组.添加(1)
go func(){
对于j:=0;j<10;j++{
ch默认情况下,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例程完成(并且隐式地接收到所有值)后,通道才会关闭。我认为您的原始代码存在一些问题
您正在关闭频道,然后再从中读取
使用10个goroutine并没有什么好处,因为你的频道是1“大小的”。所以一个goroutine每次只能产生一个结果
我的解决方案是生成一个新的goroutine来监视这10个goroutine是否完成了它的工作。在那里,您将使用您的WaitGroup
那么代码应该是这样的:
主程序包
进口(
“fmt”
“运行时”
“同步”
)
var wg sync.WaitGroup
func main(){
ch:=制造(成交量,10)
对于i:=0;i<10;i++{//创建10个go例程并添加到waitgroup
工作组.添加(1)
go func(){
对于j:=0;j<10;j++{
这是一种选择,但我不会那样做。我同意,这并不理想,因此有了“变通”这个词关于最佳实践的警告。请参阅更新。@Adrian,我同意你的观点,第一种方法不是解决问题的正确方法,我只是简单地说明了OP陷入僵局的原因。@TravisHegner我已经尝试了你的解决方案,效果很好,我接受了你的答案。我只是想检查一下我的理解是否正确正确,当我们创建单独的go例程时(让例程X)对于等待组等待和关闭通道,此单独的例程正在等待,而不是主例程。因此,一旦所有go例程完成,主例程将开始接收从第一个for循环中创建的多个例程发送到通道的值,x例程将开始恢复并关闭通道,从而停止读取通道的范围。@BhanuReddy是的,这是正确的。发送go例程只能继续,因为主例程能够同时读取通道的值,并且通道必须保持打开状态,直到发送例程完成。在真实场景中,缓冲通道可以增加吞吐量并减少上下文切换。您看到最后一个示例没有打印出您添加到通道中的int
s列表?这是因为在运行循环之前关闭了通道。然后,您将再次获得所有go例程都处于休眠状态的死锁。这是因为没有运行ad ch的go例程将永远不会再次更改。作为一般规则,写入c的go例程通道应该是关闭通道的通道。在不与其他go例程协调的情况下关闭,将保证写入关闭通道时出现恐慌。@colminator多个写入程序的情况并非如此,因为每个写入程序都不知道是否所有写入程序都已完成。因此使用WaitGroup
并从中关闭通道在编剧之外。@JamilloSantos是的,你是对的,我已经正确地更新了代码now@Adrian这个Q已经经过了几次代码编辑-我看到的版本有一个关闭频道的主围棋程序,与其他围棋程序的完成不协调。我认为我们在同一页上-即使有多个编剧,编剧的经理也应该d关闭通道,而不是主(读卡器)go例行程序
go func() {
wg.Wait() //wait for all go routines to complete
close(ch) // closing channel after completion of wait fo go routines
}()