【问题标题】:Forever channel terminating the program and go channel with RabbitMQ consumer永久通道终止程序并与 RabbitMQ 消费者一起进入通道
【发布时间】:2020-10-03 05:25:18
【问题描述】:

我正在用 Go 编写程序,同时也是使用 Go 通道的 RMQ 消费者,并遇到了这些场景。

“go forever channel”阻塞主线程,直到它从其他 go 例程获得停止信号。

但下面的程序1告诉死锁错误,程序2工作正常,没有死锁错误, 为什么会这样?

程序 1:Go 例程打印元素循环和死锁错误

package main
import "fmt"

func main() {
    stopProgram := make(chan bool)

    go func() {
      for i := 0; i < 5; i++ {
         fmt.Println("hello ",i)
      }
      // Send signal through stopProgram to stop loop
      //stopProgram <- true
    }()


   // your problem will wait here until it get stop signal through channel
   <-stopProgram
   fmt.Println("after forever channel")
}

输出

hello  0                                                                                                                                                      
hello  1                                                                                                                                                      
hello  2                                                                                                                                                      
hello  3                                                                                                                                                      
hello  4                                                                                                                                                      
fatal error: all goroutines are asleep - deadlock!                                                                                                            

goroutine 1 [chan receive]:                                                                                                                                   
main.main()                                                                                                                                                   
        /home/main.go:26 +0x73                                                                                                                                

方案 2:去路由循环接收 RMQ 交付并且没有死锁

package main
import (
    "fmt"
    )
func main() {
    // assuming some code of registring exchange and queues with rabbitmq

   msgs, err := ch.Consume(
                q.Name, // queue
                "",     // consumer
                true,   // auto-ack
                false,  // exclusive
                false,  // no-local
                false,  // no-wait
                nil,    // args
    )

    stopProgram := make(chan bool)

    go func() {
            for d := range msgs {
                  fmt.Println("reveived message ",d.Body)

            }
    }()

    // your problem will wait here until it get stop signal through channel
    <-stopProgram
    fmt.Println("after forever channel")
}

任何人都可以在这里清除永久频道在这里如何工作的事情(我是 GO 新手)吗?

我的假设 - 在程序 1 中,go 路由在打印 hello 5 次后结束,并且当前例程/任何其他例程中没有无限执行或停止信号以永远进入通道。

如果我们想永远使用 go 通道(或阻塞主要的 Go 例程以留在特定的 go 例程中),我们必须确保这些事情

  1. 无论是 go 例程都确保无限执行或

  2. Go 例程将停止信号发送到永久通道。

【问题讨论】:

    标签: go rabbitmq deadlock channel producer-consumer


    【解决方案1】:

    当您的代码在没有人发送任何内容的频道上等待时,您会收到fatal error: all goroutines are asleep - deadlock!。因此,在该频道上等待某些内容是没有意义的。

    当您尝试在没有人收听的频道上发送内容时,也会发生这种情况。

    如果您希望在特定的 go 例程完成之前阻塞,使用 waitgroups 的以下代码是一个很好的最佳方法。

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    func main() {
        var wg sync.WaitGroup
        wg.Add(1)
        go func() {
            defer wg.Done()
            for i := 0; i < 5; i++ {
                fmt.Println("hello ", i)
            }
        }()
    
        wg.Wait()
    }
    

    在程序 1 中,在 &lt;-stopProgram 处执行所有其他例程。之后,运行时知道没有人在stopProgram 上发送任何内容。因此错误

    我不确定您共享的示例代码中的Program 2 是否完整。因为即使在那里,您实际上也没有在stopProgram 上发送任何内容。所以

    【讨论】:

      猜你喜欢
      • 2017-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-27
      • 2017-06-06
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      相关资源
      最近更新 更多