Goroutines always perform "last in first order,"

In the interest of learning more about Go, I played with goroutines and noticed something - but I'm not sure what I see, and I hope that someone there can explain the following behavior.

The following code does exactly what you 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 that the code is changing as shown below, it always returns with the last first - it 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 iteration order of the loop does not change, so I assume it has something to do with goroutines ... basically, I'm trying to understand why it behaves this way ... I understand that goroutines can work in a different order than the order, in which they are generated, but, my question is, why does this always work like that. as if there is something really obvious there, I miss ...

+6
source share
2 answers

As expected, the output 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 $ 

Do you work on the Go playground? The Go playground is deterministic in design, making caching easier.

Or, do you work with runtime.GOMAXPROCS = 1? This is done one at a time, sequentially. This is what the Go Playground does.

+2
source

Go routines are scheduled randomly since Go 1.5. Thus, even if the order looks consistent, it does not rely on it .

See Go to version 1.5 :

In Go 1.5, the order in which voice plans are planned has been changed. Scheduler properties have never been defined by the language, but programs that depend on the scheduling order may be violated by this change. We have seen several (erroneous) programs affected by this change. If you have programs that implicitly depend on the planning order, you will need to update them.

Another potentially dangerous change is that the runtime now sets the default number of threads that will run simultaneously, determined by GOMAXPROCS, to the number of cores available on the CPU. In previous versions, the default was 1. Programs that do not expect to run with multiple cores may inadvertently break. They can be updated by removing the restriction or by setting GOMAXPROCS explicitly. See the project documentation for a more detailed discussion of this change.

+3
source

All Articles