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

时间:2013-06-21 03:25:12

标签: go scheduler

我有一个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()时,一切运行良好。

3 个答案:

答案 0 :(得分:1)

当main返回时,程序终止。它不会等待任何goroutines完成。因此,所有goroutine是否及时完成取决于调度程序,以及相当长的随机性,巧合和外部因素。 1e4和1e4 + 1次迭代之间的差异可能是那些影响调度的因素之一,只有那一点能够及时完成goroutine。

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

与实际问题无关,您的代码过于复杂且对其正在进行的操作非常简单。您可以按如下方式重写goroutine函数:

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

答案 1 :(得分:0)

等待goroutine完成后你需要睡一秒钟或阻止一段时间!!

答案 2 :(得分:0)

  

Go statements

     

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

GoStmt = "go" Expression .
     

功能值和参数按照常规进行评估   调用goroutine,但不像常规调用,程序执行   不等待调用的函数完成。

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