处理goroutine时奇怪的事情

时间:2013-11-22 07:01:12

标签: go println goroutine

有两件奇怪的事情。

  1. 我在片中制作了1000个数字,但它只打印246,为什么是246?为什么不是1000?

  2. 如果我删除“log.Println(”嘿嘿“)”这一行,为什么只打印0?

  3. 我知道它可能有同步问题,但我之前没有写任何同步程序,所以任何文章都可以推荐?

    import (
          "log"
          "runtime"
    )
    
    func main() {
    
      count := 1000
      slice := make([] int,count)
      for i := 0; i <= count-1; i++ {
       slice[i] =i
      }
      for _,v := range slice{
        go echo(v)
      }
      log.Println("hey")//if delete this line,it just print 0
      runtime.Gosched()
    }
    
    
    func echo(v int) {
      log.Println(v)
    }
    

2 个答案:

答案 0 :(得分:3)

无法保证在主例程完成之前运行任何go例程。当主例程完成时,程序退出而不等待您创建的所有go例程完成(甚至开始)。

解决此问题的最简单方法是分配同步通道,将其传递给每个echo实例,并在日志语句之后将令牌写入其中。然后主线程应在返回之前从该通道读取count个令牌。

答案 1 :(得分:3)

如果退出main go例程,它不会等待任何已经运行的例程。您需要同步正在运行的例程,根据我的经验,sync.WaitGroup是正确的通用解决方案。

Playground

import (
    "log"
    "sync"
)

func main() {

    count := 1000
    slice := make([]int, count)
    for i := 0; i <= count-1; i++ {
        slice[i] = i
    }
    wg := new(sync.WaitGroup)
    for _, v := range slice {
        wg.Add(1)
        go echo(v, wg)
    }
    wg.Wait()
}

func echo(v int, wg *sync.WaitGroup) {
    defer wg.Done()
    log.Println(v)
}