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 が時間内に終了するかどうかは、スケジューラに依存し、ひいてはかなりのランダム性、偶然性、および外部要因に依存します。1e4 反復と 1e4+1 反復の違いは、ゴルーチンを時間内に終了させる 1 ビットだけでスケジューリングに影響を与える要因の 1 つかもしれません。

終了する前に goroutine を終了する必要がある場合は、sync.WaitGroup などを使用して終了するまで待ちます。

実際の問題とは関係ありませんが、あなたのコードは非常に複雑であり、それが行っていることに対して一様です。ゴルーチン関数を次のように書き直すことができます。

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

ゴルーチンが終了するのを待って、しばらくスリープするか、ブロックする必要があります!!

于 2013-06-21T03:51:40.673 に答える
0

Go ステートメント

「go」ステートメントは、同じアドレス空間内で制御の独立した並行スレッド、またはゴルーチンとして関数呼び出しの実行を開始します。

GoStmt = "go" Expression .

関数の値とパラメーターは、呼び出し元のゴルーチンで通常どおり評価されますが、通常の呼び出しとは異なり、プログラムの実行は呼び出された関数が完了するのを待ちません。

最後の送信c2 <- iが完了すると、プログラムは終了する可能性があり、呼び出された関数が完了するのを待つ必要はありません。receive, v, ok := <-c2, c - 1 回の実行を完了することが保証されるだけです。ここで、c はループ カウントで、テストでは 10000 または 10001 です。

于 2013-06-21T03:53:38.873 に答える