0

我有一个golang代码示例如下(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()
    }
}
  • 当循环计数为奇数时,例如 10001,代码将输出所有数字。
  • 当循环计数为偶数时,例如 10000,代码将输出除最后一个之外的所有数字!

这是为什么?

我已经测试了从小到 2 到大到 10000 的数字,它们都遵守上述规则!

ENV如下:

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

我认为这与go sched有关。

我汇编代码:

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

10000 和 10001 之间的唯一区别是:

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

而且,最后但并非最不重要的一点是,当我添加时runtime.Gosched(),一切运行良好。

4

3 回答 3

1

当 main 返回时,程序终止。它不会等待任何 goroutine 完成。因此,是否所有的 goroutine 都按时完成取决于调度程序,进而取决于相当多的随机性、巧合性和外部因素。1e4 和 1e4+1 迭代之间的差异可能是影响调度的因素之一,它仅影响 goroutine 及时完成的​​那一位。

如果您确实需要 goroutine 在退出之前完成,请等待它完成,例如使用 sync.WaitGroup。

与实际问题无关,您的代码对于它正在做的事情来说过于复杂和单一。你可以重写 goroutine 函数如下:

for v := range c2 {
    println("c2 =", v,"numof routines:",runtime.NumGoroutine())
}
于 2013-06-21T03:53:54.260 回答
0

你需要再睡一会或者阻塞一会儿等待 goroutine 完成!!

于 2013-06-21T03:51:40.673 回答
0

Go 语句

“go”语句在同一地址空间内以独立并发控制线程或 goroutine 的形式开始执行函数调用。

GoStmt = "go" Expression .

函数值和参数在调用 goroutine 中像往常一样被评估,但与常规调用不同,程序执行不会等待调用的函数完成。

一旦最终发送c2 <- i完成,程序就可以终止,它不必等待调用的函数完成。您只能保证完成接收,,v, ok := <-c2c - 1 次,其中 c 是您的循环计数,在您的测试中为 10000 或 10001。

于 2013-06-21T03:53:38.873 回答