为什么当变量为奇数或偶数时,golang sched的运行方式不同? 是巧合还是注定?

I have a sample of golang code as follows(xx.go):

package main

import "runtime"

func main() {
    c2 := make(chan int)

     go func() {
        for v := range c2 {
            println("c2 =", v, "numof routines:", runtime.NumGoroutine())
        }
    }()

    for i:=1;i<=10001;i++{
        c2 <- i
        //runtime.Gosched()
    }
}
  • When the loop count is odd,say 10001,the code will output all the numbers.
  • when the loop count is even ,say 10000,the code will output all the numbers but the last!

Why is that?

I have tested numbers from as small as 2 to as large as 10000,they all obey the above rules!

the ENV is as follows:

uname -a : Linux hadoopnode25232 2.6.18-308.16.1.el5 #1 SMP Tue Oct 2 22:01:43 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux

go version : go version go1.1 linux/amd64

I think it has something to do with the go sched.

I assemble the code:

go tool 6g -S xx.go > xx.s

the only difference between 10000 and 10001 is :

33c33
< 0030 (xx.go:20) CMPQ    AX,$10001
---
> 0030 (xx.go:20) CMPQ    AX,$10000

And,last but not least, when I add runtime.Gosched(),everything runs well.

You need sleep a second or block a while wait the goroutine is finish!!

Go statements

A "go" statement starts the execution of a function call as an independent concurrent thread of control, or goroutine, within the same address space.

GoStmt = "go" Expression .

The function value and parameters are evaluated as usual in the calling goroutine, but unlike with a regular call, program execution does not wait for the invoked function to complete.

Once the final send, c2 <- i, is complete the program may terminate, it does not have to wait for the invoked function to complete. You are only guaranteed to complete executing the receive, v, ok := <-c2, c - 1 times, where c is your loop count, 10000 or 10001 in your tests.

When main returns, the program terminates. It will not wait for any goroutines to finish. So whether all goroutines finish in time or not depends on the scheduler, and by extension on a fair bit of randomness, coincidence and external factors. The difference between 1e4 and 1e4+1 iterations might be one of those factors that affects the scheduling in just that one bit that makes the goroutine finish in time.

If you really require the goroutine to finish before exitting, wait for it to finish, by employing for example a sync.WaitGroup.

Unrelated to the actual issue, your code is overly complex and unidiomatic for what it's doing. You could rewrite the goroutine function as follows:

for v := range c2 {
    println("c2 =", v,"numof routines:",runtime.NumGoroutine())
}