代码之家  ›  专栏  ›  技术社区  ›  somejkuser

并发示例中的值不正确

  •  -1
  • somejkuser  · 技术社区  · 8 年前

    我正在翻阅一本电子书,这里我正在编写以下代码:

    func f(n int) {
      for i := 0; i < 10; i++ {
        fmt.Println(n, ":", i)
        amt := time.Duration(rand.Intn(250))
        time.Sleep(time.Millisecond * amt)
      }
    }
    
    func ConcurrMain() {
      for i := 0; i < 10; i++ {
        go f(i)
      }
      fmt.Println("hi")
    }
    

    问题是,我通过每个run命令检索不同的值 goclipse . 如果不执行sleep命令,效果会更好。

    无论如何,我认为任何一步一步的解释都有助于我学习并发性。

    下面是我的时间睡眠返回值的一个例子:

    4 : 0
    1 : 0
    6 : 0
    0 : 0
    5 : 0
    7 : 0
    8 : 0
    2 : 0
    3 : 0
    9 : 0
    9 : 1
    hi
    

    然后我再运行一次,现在我有了时间睡眠:

    0 : 0
    hi
    1 : 0
    

    现在是第三次,我有时间睡觉:

    0 : 0
    hi
    

    而这次 不睡觉 我得到:

    1 : 0
    1 : 1
    1 : 2
    1 : 3
    1 : 4
    1 : 5
    1 : 6
    1 : 7
    1 : 8
    3 : 0
    3 : 1
    4 : 0
    4 : 1
    4 : 2
    9 : 0
    6 : 0
    6 : 1
    6 : 2
    2 : 0
    2 : 1
    2 : 2
    2 : 3
    2 : 4
    2 : 5
    2 : 6
    2 : 7
    2 : 8
    2 : 9
    7 : 0
    7 : 1
    7 : 2
    7 : 3
    7 : 4
    7 : 5
    7 : 6
    5 : 0
    5 : 1
    5 : 2
    5 : 3
    5 : 4
    5 : 5
    5 : 6
    5 : 7
    5 : 8
    5 : 9
    9 : 1
    1 : 9
    8 : 0
    3 : 2
    hi
    

    我在windows下使用goclipse,以防相关信息

    更新

    需要注意的是,这个调用是从主包调用的:

    func main()
    {
       lab.ConcurrMain()
    }
    

    更新2

    我补充道: var wg sync.WaitGroup outside the func scope. I also added 工作组增加(1) inside the Concurrmain蛋白 method just prior to 前进F(I) , then i also added 工作组等待() just after the 执行go函数的forloop and then finally 工作组完成() 在里面 f()`method**,这似乎很有效,但电子书中没有这个答案,所以我想理解。

    1 回复  |  直到 8 年前
        1
  •  1
  •   Zak    8 年前

    在go中,程序只在主goroutine运行时才运行。即,最初运行主函数的goroutine,如果退出,则整个程序退出。

    在您最初给出的示例(代码片段)中,没有什么需要强制执行的 什么时候 你搞的那些鬼把戏 ConcurrMain 将被安排和运行。在您添加 sync.WaitGroup 主goroutine可以在调度其他goroutine之前退出。

    如果主goroutine退出,则整个程序退出,其他goroutine将不会执行。主goroutine不会等待其他goroutine,除非您特别要求它使用等待组。