【问题标题】:GoRoutines, Channels with WaitGroup unexpected outputGoRoutines,带有 WaitGroup 意外输出的 Channels
【发布时间】:2015-08-11 23:37:06
【问题描述】:

我看了很久以前写的一些代码,当时go1.3发布(我可能错了)。 CODE HERE

以下代码曾经按预期工作,但现在由于我已将 go 更新到当前的主版本(go version devel +bd1efd5 Fri Jul 31 16:11:21 2015 +0000 darwin/amd64),最后输出消息c <- "FUNC 1 DONE" 没有打印,代码在play.golang.org 上正常工作。是我做错了什么,还是这是一个错误?

package main

import ("fmt";"sync";"time")

func test(c chan string, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Println("EXEC FUNC 1")
  time.Sleep(3 * time.Second)
  c <- "FUNC 1 DONE"
}

func test1(c chan string, wg *sync.WaitGroup) {
  defer wg.Done()
  fmt.Println("EXEC FUNC 2")
  time.Sleep(2 * time.Second)
  c <- "FUNC 2 DONE"
}

func main() {
  ch := make(chan string)

  var wg sync.WaitGroup
  wg.Add(2)

  go test(ch, &wg)
  go test1(ch, &wg)

  go func(c chan string) {
    for txt := range c {
      fmt.Println(txt)
    }
  }(ch)

  wg.Wait()
}

更新:

我不是说,上面是做这些类型工作的最好方法,但我看不出有什么问题。

同样在go version go1.4.2 darwin/amd64 中运行它会返回预期的输出。

【问题讨论】:

    标签: go


    【解决方案1】:

    您的代码一直有这个错误。您的程序在 main 退出之前设法打印所有消息只是偶然的。

    为了使这项工作正常进行,我将反转您拥有wg.Wait() 和通道接收的位置,以便您可以异步关闭通道。这样接收操作就阻塞了main,一旦所有发送操作完成,通道就会关闭。

    func main() {
        ch := make(chan string)
    
        var wg sync.WaitGroup
        wg.Add(2)
    
        go test(ch, &wg)
        go test1(ch, &wg)
    
        go func() {
            wg.Wait()
            close(ch)
        }()
    
        for txt := range ch {
            fmt.Println(txt)
        }
    }
    

    【讨论】:

    • 我认为应用在单线程上运行时不会出现此问题。 go1.4 及更早版本默认运行为 GOMAXPROCS=1。 1.5+ 已更改为 GOMAXPROCS=NumCPU。这可以解释这个错误的突然出现。
    • @tidwall:不,调度程序让最后一个打印语句通过只是偶然。您可以通过使用 go1.5 运行 GOMAXPROCS=1 轻松测试这一点,它显示了相同的损坏输出(至少在我的系统上。结果在技术上是不确定的,因为没有定义的 goroutine 执行顺序)。
    • @JimB 对我来说相同,将 GOMAXPROCS 设置为 1 仍会输出相同的损坏输出。
    • @alexsmn:是的,完全正确。这不一定是 GOMAXPROCS 的变化,而是运行时的变化导致 goroutine 的执行顺序略有不同。原始代码永远不正确。
    • @JimB:确实我错了。我得到和你一样的结果。代码中有一个明显的错误;在最终 fmt.Println 之前,正在接收 chan msg 并且正在释放 WaitGroup 以允许 main 返回。
    猜你喜欢
    • 1970-01-01
    • 2015-12-26
    • 2011-03-29
    • 2016-08-20
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多