dongqiao6730 2016-02-02 12:03
浏览 47
已采纳

goroutine总是执行“后进先出”

in the interests of learning more about Go, I have been playing with goroutines, and have noticed something - but am not sure what exactly I'm seeing, and hope someone out there might be able to explain the following behaviour.

the following code does exactly what you'd expect:

package main

import (
  "fmt"
)

type Test struct {
  me int
}

type Tests []Test

func (test *Test) show() {
  fmt.Println(test.me)

}

func main() {
  var tests Tests
  for i := 0; i < 10; i++ {
    test := Test{
      me: i,
    }
    tests = append(tests, test)
  }

  for _, test := range tests {
    test.show()
  }

}

and prints 0 - 9, in order.

now, when the code is changed as shown below, it always returns with the last one first - doesn't matter which numbers I use:

package main

import (
    "fmt"
    "sync"
)

type Test struct {
    me int
}

type Tests []Test

func (test *Test) show(wg *sync.WaitGroup) {
    fmt.Println(test.me)
    wg.Done()

}

func main() {
    var tests Tests
    for i := 0; i < 10; i++ {
        test := Test{
            me: i,
        }
        tests = append(tests, test)
    }

    var wg sync.WaitGroup
    wg.Add(10)
    for _, test := range tests {
        go func(t Test) {
            t.show(&wg)
        }(test)
    }
    wg.Wait()

}

this will return: 9 0 1 2 3 4 5 6 7 8

the order of iteration of the loop isn't changing, so I guess that it is something to do with the goroutines... basically, I am trying to understand why it behaves like this...I understand that goroutines can run in a different order than the order in which they're spawned, but, my question is why this always runs like this. as if there's something really obvious I'm missing...

  • 写回答

2条回答 默认 最新

  • dougui2254 2016-02-02 12:51
    关注

    As expected, the ouput is pseudo-random,

    package main
    
    import (
        "fmt"
        "runtime"
        "sync"
    )
    
    type Test struct {
        me int
    }
    
    type Tests []Test
    
    func (test *Test) show(wg *sync.WaitGroup) {
        fmt.Println(test.me)
        wg.Done()
    
    }
    
    func main() {
        fmt.Println("GOMAXPROCS", runtime.GOMAXPROCS(0))
        var tests Tests
        for i := 0; i < 10; i++ {
            test := Test{
                me: i,
            }
            tests = append(tests, test)
        }
    
        var wg sync.WaitGroup
        wg.Add(10)
        for _, test := range tests {
            go func(t Test) {
                t.show(&wg)
            }(test)
        }
        wg.Wait()
    
    }
    

    Output:

    $ go version
    go version devel +af15bee Fri Jan 29 18:29:10 2016 +0000 linux/amd64
    $ go run goroutine.go
    GOMAXPROCS 4
    9
    4
    5
    6
    7
    8
    1
    2
    3
    0
    $ go run goroutine.go
    GOMAXPROCS 4
    9
    3
    0
    1
    2
    7
    4
    8
    5
    6
    $ go run goroutine.go
    GOMAXPROCS 4
    1
    9
    6
    8
    4
    3
    0
    5
    7
    2
    $ 
    

    Are you running in the Go playground? The Go playground, by design, is deterministic, which makes it easier to cache programs.

    Or, are you running with runtime.GOMAXPROCS = 1? This runs one thing at a time, sequentially. This is what the Go playground does.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度