在没有等待组的情况下,从不同的go例程将数据写入同一个chanel中工作正常

在没有等待组的情况下,从不同的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

在等待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++ { // 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
    }()